如果在AsyncTaskLoader运行期间发生方向更改,则不会调用LoaderCallbacks.onLoadFinished

时间:2011-08-23 19:20:15

标签: android

使用android-support-v4.jar和FragmentActivity(此时没有片段)

我有一个AsyncTaskLoader,我开始加载,然后在后台线程仍在运行时更改方向。在我的日志中,我看到响应来自后台请求。响应完成,我希望调用onLoadFinished(),但它永远不会。

作为故障排除的一种方法,在Manifest中,如果我设置android:configChanges =“orientation”onLoadFinished()按预期调用。

我的Activity实现了加载器回调。在LoaderManager.initLoader()的源代码中,我看到如果加载器已经存在,则新的回调设置为LoaderInfo内部对象类,但我没有看到再次调用Loader.registerListener()的位置。只有在调用LoaderManagerImpl.createAndInstallLoader()时才会调用registerListener。

我怀疑由于活动在方向更改时被销毁并重新创建,并且由于它是回调的监听器,因此未注册新活动以进行通知。

任何人都可以确认我的理解以及解决方案是什么,以便在更改方向后调用onLoadFinished?

2 个答案:

答案 0 :(得分:34)

Nikolay发现了这个问题 - 谢谢。

我在onResume()上调用了initLoader。 Android文档声明:

  

“您通常在活动的onCreate()中初始化Loader   方法,或在片段的onActivityCreated()方法中。“

阅读“典型”比处理配置更改生命周期时更加强调。

我将initLoader调用移动到onCreate(),这解决了我的问题。

我认为原因是在FragmentActivity.onCreate()中,从LastNonConfigurationInstance和FragmentActivity.onStart()中提取了LoaderManagers的集合,有一些关于Loaders和LoaderManagers的启动工作。在调用onResume()时,事情已经在进行中。当Loader第一次需要实例化时,从外部onCreate()调用initLoader仍然有效。

答案 1 :(得分:3)

实际上,initLoader()onCreate()的调用并非正在修复它。这是对getLoaderManager()的调用。总之,发生的事情是,当一个活动重新启动时,它已经知道了加载器。当您的活动点击onStart()时,它会尝试重新启动它们,但它会在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;
}

由于尚未调用getLoaderManager(),mLoaderManager为空。因此,它会跳过第一个条件并调用mLoaderManager.doStart()

您只需在getLoaderManager()中拨打onCreate()即可对此进行测试。你不需要在那里调用init / restart加载器。

这对我来说真的像个错误。

*即使您没有使用片段,这也是代码路径,所以不要对此感到困惑。