Android Loader在屏幕旋转时没有触发回调

14

我正在使用 AsyncTaskLoader。我的一个活动已经实现了LoaderCallbacks(支持库)。

我设置了断点和日志,发现加载器成功返回结果,但第二次回调时onLoadFinished没有被触发。奇怪的是 - 当我再次旋转后它就奏效了,无论我从哪个方向开始,在返回时都会得到回调。

在我的活动中的onResume方法中:

LoaderManager lm = getSupportLoaderManager();
Loader loader = lm.initLoader(0, null, new LoaderManager.LoaderCallbacks<String>() {

        @Override
        public Loader<String> onCreateLoader(int i, Bundle bundle) {
            Loader<String> loader = new TestLoader(MainActivity.this);
            return loader;
        }

        @Override
        public void onLoadFinished(Loader<String> stringLoader, String s) {
            Log.d(Application.TAG, "OnLoadFinished " + s);
            doStuff(s);
        }

        @Override
        public void onLoaderReset(Loader<String> stringLoader) {
            // NOP
        }
    });

在我的加载器中:

public class TestLoader extends AsyncTaskLoader<String> {
    private String mData;

    public TestLoader(Context context) {
        super(context);
    }

    // This get's called after a loader is initialized or a loader 
    // that is alive still is reset
    @Override
    public void onStartLoading() {
        if (mData != null) { // Have our data loaded, just deliver it!
            deliverResult(mData);
        }
        if (takeContentChanged() || mData == null) {
            forceLoad();
        }
    }

    // This is called when an Activity or Fragment requests a loader 
    // to be reset because they want new data
    @Override
    public void onReset() {
        mData = null;
        // Ensure that the old task is cancelled if it was running
        // We do NOT have to call forceLoad here because onStartLoading 
        // will get called after this
        cancelLoad();
    }

    // Here we just want to store our own data we got and reset our boolean
    @Override
    public void deliverResult(String data) {
        Log.d(Application.TAG, "deliverResult " + data);
        mData = data;
        super.deliverResult(mData);
    }

    @Override
    public String loadInBackground() {
       // returns content from a content provider ... 
    }
}

这个问题让我十分困惑,我是 Android 新手,也许对其他人来说很明显 :)


1
我也一直在努力解决这个问题,但我对Android也很陌生。我能够做出改变的唯一方法是确保在Activity的onCreate()中调用get(Support)LoaderManager(),然后即使在其他地方调用initLoader(),它也可以正常工作。调试Activity类中内部加载器变量的顺序和生命周期非常困难,希望有人能理解发生了什么。 - avenmore
我也遇到了这个问题 - 我在导航监听器中调用了getSupportLOaderManager().restart。在onCreate中直接实例化并在监听器中访问它可以解决问题,但我不知道为什么.. 有人知道吗? - Thomas Clowes
onResume通常不是做这些事情的正确位置。有关详细信息,请参阅我的答案。 - Monstieur
2个回答

25
如果是Activity,则至少在onCreate()中简单调用getSupportLoaderManager() / getLoaderManager();如果是Fragment,则在onActivityCreated()中调用。实际的initLoader()可以放在其他地方。否则,即使加载完成,加载程序也会处于停止状态,不会传递结果。我怀疑这是因为加载程序管理器不会将旧加载程序重新附加到新的Activity中,除非在新的ActivityonCreate()中进行上述调用。

1
解决了我奇怪的问题,这个问题只发生在单个片段上,其他片段都正常工作。 - ingsaurabh

1
你有。
Loader loader = lm.initLoader(...)

你应该有


Loader loader = new LoaderManager.LoaderCallbacks(...) {...}

在您的onResume()中。
this.getLoaderManager().restartLoader(0, null, this.loader);

请参阅加载器文档


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接