LoaderCallbacks.onLoadFinished not called if orientation change happens during AsyncTaskLoader run

前端 未结 2 1898
野的像风
野的像风 2020-12-01 10:53

Using android-support-v4.jar and FragmentActivity (no fragments at this point)

I have an AsyncTaskLoader which I start loading and then change the orientation while

相关标签:
2条回答
  • 2020-12-01 11:29

    Nikolay identified the issue - Thank you.

    I was calling initLoader fron onResume(). The Android documentation states:

    "You typically initialize a Loader within the activity's onCreate() method, or within the fragment's onActivityCreated() method."

    Read "typically" as a bit more emphatic than I did when it comes to dealing with configuration change life cycle.

    I moved my initLoader call to onCreate() and that solved my problem.

    I think the reason is that in FragmentActivity.onCreate() a collection of LoaderManagers is pulled from LastNonConfigurationInstance and in FragmentActivity.onStart() there is some start up work regarding Loaders and LoaderManagers. Things are already in process by the time onResume() is called. When the Loader needs instantiated for the first time, calling initLoader from outside onCreate() still works.

    0 讨论(0)
  • 2020-12-01 11:37

    It's actually not the call to initLoader() in onCreate() that's fixing it. It's the call to getLoaderManager(). In summary, what happens is that when an activity is restarted, it already knows about the loaders. It tries to restart them when your activity hits onStart(), but then it hits this code in FragmentHostCallback.doLoaderStart()*:

    void doLoaderStart() {
        if (mLoadersStarted) {
            return;
        }
        mLoadersStarted = true;
    
        if (mLoaderManager != null) {
            mLoaderManager.doStart();
        } else if (!mCheckedForLoaderManager) {
            mLoaderManager = getLoaderManager("(root)", mLoadersStarted, false);
            // WTF: Why aren't we calling doStart() here?!
        }
        mCheckedForLoaderManager = true;
    }
    

    Since getLoaderManager() wasn't called yet, mLoaderManager is null. It therefore skips the first condition and the call to mLoaderManager.doStart().

    You can test this by simply putting a call to getLoaderManager() in onCreate(). You don't need to call init / restart loaders there.

    This really seems like a bug to me.

    * This is the code path even if you aren't using fragments, so don't get confused by that.

    0 讨论(0)
提交回复
热议问题