Android, AsyncTask, статус проверки?

#android

#Android

Вопрос:

Это мой код:

В 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();
    }
}
  

Если музыка не загрузилась, я получаю исключение nullpointer, просматривая документы, я вижу, что есть GetStatus(), но я пробовал что-то вроде этого:

 music_load_status=LoadMusicInBackground.getStatus()
  

и это не работает 🙁
Как мне проверить, завершена ли фоновая задача и загружена ли музыка?

Спасибо!
Райан

Ответ №1:

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 .

Комментарии:

1. Чтобы уточнить: ЗАВЕРШЕНО — это статус ПОСЛЕ вызова onPostExecute. Если вы проверите статус во время выполнения onPostExecute, статус будет ЗАПУЩЕН

2. тогда почему он возвращает ЗАПУСК в postexcute, это немного удивительно

3. также стоит упомянуть, что, если задача была отменена вызовом метода cancel(), она все равно будет возвращать статус ВЫПОЛНЕНИЯ.

4. @user2758776 Он должен возвращаться к работе до тех пор, пока «onPostExecute» еще не был вызван. Вызов cancel фактически не останавливает поток. Он просто сообщает потоку, что для него была вызвана отмена.

5. @Matthias: Хороший улов. Глядя на исходный код, похоже, что это было до Honeycomb. Теперь вместо onPostExecute(результат объекта) вместо этого вызывается onCancelled(результат объекта), но теперь должно быть установлено значение FINISHED . Похоже, вам всегда нужно проверять «isCanceled ()», чтобы быть в безопасности.

Ответ №2:

Это асинхронное программирование — вы не должны проверять из потока пользовательского интерфейса, потому что это означает, что вы блокируете поток пользовательского интерфейса (предположительно, запускаете проверку в цикле с помощью Thread.sleep()?).

Вместо этого вы должны вызываться при выполнении AsyncTask: из него onPostExecute() вызывается любой метод в Activity, который вам нужен.

Предостережение: недостатком этого подхода является то, что активность должна быть активной при завершении фонового потока. Часто это не так, например, если выполняется возврат назад или изменяется ориентация. Лучший подход — отправить широковещательную onPostExecute() рассылку, а затем заинтересованные действия могут зарегистрироваться для ее получения. Самое приятное, что Activity получает широковещательную рассылку только в том случае, если она активна в это время, что означает, что могут регистрироваться несколько Activities, но только активный получит его.

Ответ №3:

Создать асинхронную задачу с помощью прослушивателя

 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);
    }
}
  

И использовать асинхронную задачу

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

Я надеюсь, что это может помочь некоторым людям