Fragment calling onDestroyView but reference to adapter is null

1037 views android
3

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)

In Fragment below the onCreateView will start an Observable timer where when it reaches 3 seconds the adapter issueAdapter will be instantiated. And then when onDestroyView is called, it will do some cleanups (setting issueAdapter.setOnKeyListener to null, for example)

Programatically the fragment should only be destroyed after 30 seconds (leaving time to issuesAdapter be instantiated). This is the first time I received that exception in maybe a year of production.

My question is, is that possible I'm missing some lifecycle aware code handler?

Obs.: The device don't allow rotation.

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

Thanks

answered question

1 Answer

12

Rotation is not the only configuration change that could possibly trigger your Fragment's destruction and re-creation. Additionally, the Fragment could be destroyed even without a configuration change; perhaps the user opened this screen and then immediately received a phone call, and their device killed your app's process to conserve resources.

All in all, even if you think onDestroyView() "shouldn't" be called before the three seconds are up, you still need to handle the fact that it can be.

Seems simple enough in this case: just check if issueAdapter is null before you try to null out its key listener.

posted this

Have an answer?

JD

Please login first before posting an answer.