使用android-support-v4.jar和FragmentActivity(此时没有片段)
我有一个AsyncTaskLoader,我开始加载,然后在后台线程仍在运行时更改方向。在我的日志中,我看到响应来自后台请求。响应完成,我希望调用onLoadFinished(),但它永远不会。
作为故障排除的一种方法,在Manifest中,如果我设置android:configChanges =“orientation”onLoadFinished()按预期调用。
我的Activity实现了加载器回调。在LoaderManager.initLoader()的源代码中,我看到如果加载器已经存在,则新的回调设置为LoaderInfo内部对象类,但我没有看到再次调用Loader.registerListener()的位置。只有在调用LoaderManagerImpl.createAndInstallLoader()时才会调用registerListener。
我怀疑由于活动在方向更改时被销毁并重新创建,并且由于它是回调的监听器,因此未注册新活动以进行通知。
任何人都可以确认我的理解以及解决方案是什么,以便在更改方向后调用onLoadFinished?
答案 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加载器。
这对我来说真的像个错误。
*即使您没有使用片段,这也是代码路径,所以不要对此感到困惑。