Фрагмент, вызывающий onDestroyView, но ссылка на адаптер пуста - PullRequest
0 голосов
/ 12 сентября 2018
java.lang.NullPointerException: Attempt to invoke virtual method 'void my.app.ui.fragment.adapter.IssueAdapter.setOnKeyListener(my.app.fragment.adapter.IssueAdapter$OnItemListener)' on a null object reference
    at MyFragment.onDestroyView(MyFragment.java:429)
    at android.support.v4.app.Fragment.performDestroyView(Fragment.java:2565)
    at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1512)
    at android.support.v4.app.FragmentManagerImpl.moveFragmentToExpectedState(FragmentManager.java:1759)
    at android.support.v4.app.BackStackRecord.executeOps(BackStackRecord.java:792)
    at android.support.v4.app.FragmentManagerImpl.executeOps(FragmentManager.java:2596)
    at android.support.v4.app.FragmentManagerImpl.executeOpsTogether(FragmentManager.java:2383)
    at android.support.v4.app.FragmentManagerImpl.removeRedundantOperationsAndExecute(FragmentManager.java:2338)
    at android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:2245)
    at android.support.v4.app.FragmentManagerImpl$1.run(FragmentManager.java:703)
    at android.os.Handler.handleCallback(Handler.java:739)
    at android.os.Handler.dispatchMessage(Handler.java:95)
    at android.os.Looper.loop(Looper.java:145)
    at android.app.ActivityThread.main(ActivityThread.java:6939)
    at java.lang.reflect.Method.invoke(Method.java:-2)
    at java.lang.reflect.Method.invoke(Method.java:372)
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1404)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1199)

В Fragment ниже onCreateView запустится наблюдаемый таймер, где, когда он достигнет 3 секунд, будет создан экземпляр адаптера issueAdapter. И затем, когда вызывается onDestroyView, он выполнит некоторые очистки (например, для параметра issueAdapter.setOnKeyListener будет установлено значение null)

Программно фрагмент должен быть уничтожен только через 30 секунд (оставлено время для создания экземпляров вопроса Adapter). Впервые я получил это исключение, возможно, за год производства.

У меня вопрос: возможно ли, что мне не хватает обработчика кода, поддерживающего жизненный цикл?

Obs .: Устройство не допускает вращения.

private final CompositeDisposable disposables = new CompositeDisposable();
private IssueAdapter issueAdapter;    

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    ViewGroup rootView = (ViewGroup) inflater.inflate(my_fragment, container, false);
    unbinder = ButterKnife.bind(this, rootView);

    disposables.add(
            Observable
                    .timer(3, TimeUnit.SECONDS)
                    .subscribeOn(Schedulers.io())
                    .observeOn(AndroidSchedulers.mainThread())
                    .subscribe(__ -> {
                        List<Issue> issues = AppRepository.getInstance().getIssues();
                        issueAdapter = new IssueAdapter(issues);
                        issueAdapter.setOnKeyListener(position -> {
                            this.issueSelected = issues.get(position);
                        });
                    }, ErrorService::notify)
    );

    return rootView;
}

@Override
public void onDestroyView() {
    super.onDestroyView();

    issueAdapter.setOnKeyListener(null);
    unbinder.unbind();
}

@Override
public void onDestroy() {
    super.onDestroy();

    disposables.clear();
}

Спасибо

Ответы [ 3 ]

0 голосов
/ 12 сентября 2018

Можете ли вы сделать условие безопасности для адаптера, потому что объект существует, когда весь процесс был успешным, но в случае ошибки, errorAdapter был нулевым, потому что не найден экземпляр.Рекомендую в свой onDestroy поставить

if(issueAdapter!=null){
   issueAdapter.setOnKeyListener(null);
}
0 голосов
/ 12 сентября 2018

Как говорит Бен П., нулевая проверка была бы самым простым решением.Если вам нужно быть уверенным, что ваш IssueAdapter не очищается, вы можете добавить следующую строку в метод OnCreate в своем фрагменте.

setRetainInstance(true);

Это обеспечит тот же экземпляр (с переменными экземпляра)используется, если фрагмент воссоздан.Если вам не нужно гарантировать, что ваш IssueHandler не будет установлен в нуль, я бы не стал его использовать.

0 голосов
/ 12 сентября 2018

Вращение - не единственное изменение конфигурации, которое может спровоцировать разрушение и воссоздание вашего Фрагмента.Кроме того, фрагмент может быть уничтожен даже без изменения конфигурации;возможно, пользователь открыл этот экран, а затем сразу же получил телефонный звонок, и его устройство убило процесс вашего приложения для экономии ресурсов.

В целом, даже если вы считаете, что onDestroyView() «не следует» вызывать раньшетри секунды истекли, вам все еще нужно учесть тот факт, что это может быть.

В этом случае все выглядит достаточно просто: просто проверьте, является ли issueAdapter нулевым, прежде чем пытаться обнулить его слушатель ключа.

...