Android после того, как обработчик removeCallbacksAndMessages все еще публикует возможность запуска в фоновом потоке

Я столкнулся с необычным исключением NPE в Android с обработчиком и фоновым потоком.

Я знаю, что при уничтожении активности или фрагмента виджет пользовательского интерфейса будет уничтожен, поэтому вы должны отменить все ожидающие сообщения или запускаемые сообщения, отправленные из фона.

Например, в обратном вызове фрагмента onDestroyView я вызываю обработчик removeCallbacksAndMessages(null), чтобы удалить все обратные вызовы. Но в некоторых случаях обратный вызов все же выполнялся, но в это время пользовательский интерфейс уничтожался, NPE выбрасывало.

Ниже приведен образец:

public class SampleFragment extends Fragment {
  private Handler mHandler = new Handler() {
    @Override public void handleMessage(Message msg) {
      switch (msg.what) {
        // do your job
      }
    }
  };

  @Nullable @Override
  public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    // create some ui
    return super.onCreateView(inflater, container, savedInstanceState);
  }

  @Override public void onActivityCreated(Bundle savedInstanceState) {
    super.onActivityCreated(savedInstanceState);
    new Thread(new Runnable() {
      @Override public void run() {
        // after a long running work
        mHandler.post(new Runnable() {
          @Override public void run() {
            // OOPS, the ui widget may null!
          }
        });
      }
    }).start();
  }

  @Override public void onDestroyView() {
    mHandler.removeCallbacksAndMessages(null);
    super.onDestroyView();
  }
}

В какой-то момент я заметил, что в onDestroyView обработчик удалил все ожидающие сообщения или исполняемые файлы, которые будут прикреплены к потоку пользовательского интерфейса, а представление установлено равным нулю, чтобы быть gc. Но поток может все еще находиться в рабочем состоянии, и обработчик опубликует исполняемый, но представление будет нулевым.

Самый простой способ — проверить null из фрагмента getView() в runnable, но если во всей этой ситуации нужно проверять null, это было бы утомительно. Есть ли хороший подход к решению такой проблемы?

Спасибо заранее.


person longkai    schedule 28.01.2015    source источник
comment
Вы уверены, что вызывается метод onDestroyView?   -  person ρяσѕρєя K    schedule 28.01.2015
comment
Я уверен, что виджет пользовательского интерфейса сбрасывался этим методом.   -  person longkai    schedule 28.01.2015
comment
проверьте этот ответ stackoverflow.com/a/5844433/1360579   -  person orium    schedule 07.02.2015