安卓,AsyncTask,如何检查状态?

40
这是我的代码:
在 onCreate 里面:
 new LoadMusicInBackground().execute();

然后,在我的主类末尾我有这段代码

/** Helper class to load all the music in the background. */
class LoadMusicInBackground extends AsyncTask<Void, String, Void> {
    @Override
    protected Void doInBackground(Void... unused) {

        soundPool = new SoundPool(5, AudioManager.STREAM_MUSIC, 100);
        soundPoolMap = new HashMap<Integer, Integer>();

        soundPoolMap.put(A1,
                soundPool.load(GameScreen_bugfix.this, R.raw.a, 1));
        soundPoolMap.put(A3,
                soundPool.load(GameScreen_bugfix.this, R.raw.b, 1));
        soundPoolMap.put(A5,
                soundPool.load(GameScreen_bugfix.this, R.raw.c_s, 1));
        soundPoolMap.put(A6,
                soundPool.load(GameScreen_bugfix.this, R.raw.d, 1));
        soundPoolMap.put(A8,
                soundPool.load(GameScreen_bugfix.this, R.raw.e, 1));
        soundPoolMap.put(A10,
                soundPool.load(GameScreen_bugfix.this, R.raw.f_s, 1));
        soundPoolMap.put(A12,
                soundPool.load(GameScreen_bugfix.this, R.raw.g_s, 1));
        soundPoolMap.put(wrong,
                soundPool.load(GameScreen_bugfix.this, R.raw.wrong2, 1));

        publishProgress("");
        Log.v("SOUNDPOOL", "" + soundPoolMap);
        return (null);
    }

    @Override
    protected void onProgressUpdate(String... item) {
        // text1.setText(item[0]);
    }

    @Override
    protected void onPostExecute(Void unused) {
        //Toast.makeText(GameScreen_bugfix.this, "music loaded!", Toast.LENGTH_SHORT).show();
    }
}

如果音乐没有加载,我会得到一个空指针异常。查看文档,我发现有一个getStatus()方法,但我尝试过类似这样的代码:

music_load_status=LoadMusicInBackground.getStatus()

但是那并没有起作用 :(
我如何检查后台任务是否完成并且音乐已经加载?

谢谢!
Ryan

3个回答

171

getStatus() 检查 AsyncTask 是否处于挂起、运行或已完成状态。

LoadMusicInBackground lmib = new LoadMusicInBackground();

if(lmib.getStatus() == AsyncTask.Status.PENDING){
    // My AsyncTask has not started yet
}

if(lmib.getStatus() == AsyncTask.Status.RUNNING){
    // My AsyncTask is currently doing work in doInBackground()
}

if(lmib.getStatus() == AsyncTask.Status.FINISHED){
    // My AsyncTask is done and onPostExecute was called
}
如果您想检查操作是否成功(即音乐是否成功加载),则需要自己设计一种确定方法。 getStatus() 只能确定 AsyncTask 中实际线程的状态。

13
澄清一下:FINISHED是在执行完onPostExecute后的状态。如果你在onPostExecute期间检查状态,状态将为RUNNING。 - user123321
1
为什么在 postexecute 中返回“RUNNING”,有点令人惊讶。 - Tofeeq Ahmad
4
值得一提的是,如果通过调用 cancel() 方法来取消任务,则该任务仍将返回运行中(RUNNING)状态。 - user2758776
只要 "onPostExecute" 还没有被调用,它应该返回 RUNNING。调用 cancel 并不会真正停止线程,它只是告诉线程已经被取消了。 - DeeV
1
@Matthias:干得好。看源代码,似乎在Honeycomb之前就是这种情况了。现在,不再调用onPostExecute(Object Result),而是调用onCancelled(Object result),但现在FINISHED应该被设置。看起来你总是需要检查“isCanceled()”以保险起见。 - DeeV
显示剩余3条评论

18

这是异步编程 - 你不应该从UI线程中检查,因为这意味着你会阻塞UI线程(可能是用Thread.sleep()在循环中运行检查?)。

相反,你应该在AsyncTask完成时被调用:从它的 onPostExecute() 调用Activity中需要的任何方法。

注意:这种方法的缺点是当后台线程完成时Activity必须处于活动状态。通常情况下不是这样的,例如如果按了返回键或旋转了屏幕。更好的方法是从 onPostExecute() 发送广播,然后感兴趣的Activities可以注册接收它。最好的部分是只有在Activity处于活动状态时才会接收到广播,这意味着多个Activities可以注册,但只有活动的那个会接收到。


9
创建带有监听器的异步任务
class ClearSpTask extends AsyncTask<Void, Void, Void> {

    public interface AsynResponse {
        void processFinish(Boolean output);
    }

    AsynResponse asynResponse = null;

    public ClearSpTask(AsynResponse asynResponse) {
        this.asynResponse = asynResponse;
    }

    @Override
    protected void onPreExecute() {
        super.onPreExecute();
        showProgressDialog();
    }

    @Override
    protected Void doInBackground(Void... voids) {
        cleardata();
        return null;
    }

    @Override
    protected void onPostExecute(Void aVoid) {
        super.onPostExecute(aVoid);
        hideProgressDialog();
        asynResponse.processFinish(true);
    }
}

使用AsyncTask

new ClearSpTask(new ClearSpTask.AsynResponse() {
        @Override
        public void processFinish(Boolean output) {
            // you can go here   
        }
}).execute();

我希望这能帮助一些人


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接