【问题标题】:OnLoadFinished() called twiceOnLoadFinished() 调用了两次
【发布时间】:2013-01-21 02:30:59
【问题描述】:

我想弄清楚我是否在加载程序方面做错了什么。我正在使用支持库,并且我有一个片段,它在 onCreate() 调用 initLoader() 将自身设置为 LoaderCallbacks,但是在旋转时,它在 onLoadFinished() 中收到两次结果,一次是由于调用 init (并且它已经拥有数据),并且由于 FragmentActivity 循环遍历 onStart() 中的所有加载器并传递结果,因为它已经拥有数据。

如果我只调用一次 init(在 Fragment 首次启动时),它不会将自己设置为 Loader 的回调,因此它根本不会收到对 onLoadFinished 的调用。似乎 onLoadFinished 应该只被调用一次,因为一些昂贵的事情可能会在 onLoadFinished() 中完成(例如清除列表适配器等),所以我只是想弄清楚这是一个错误还是我是只是在错误的时间调用 init 或其他什么。

有人对此问题有任何见解吗?

【问题讨论】:

标签: android android-fragments loader android-fragmentactivity android-loadermanager


【解决方案1】:

我遇到了类似的问题,原因是我的代码中有initLoaderrestartLoader。根据用户的操作,我的查询可能会更改,因此我需要重新启动加载程序。

解决方案是仅使用restartLoader,即使在onResume 回调方法中将initLoader 替换为restartLoader

【讨论】:

    【解决方案2】:

    这是一个相当古老的问题,但对于未来的读者,我有一个替代解决方案。基本上我最终做的是重新启动加载器(如果存在)。

    public void onActivityCreated(Bundle savedInstanceState) {
    ...
           if(getLoaderManager().getLoader(Constants.LOADER_ID) == null) {
                getLoaderManager().initLoader(Constants.LOADER_ID, null, this);
            } else {
                getLoaderManager().restartLoader(Constants.LOADER_ID, null, this);
            }
    
    ...
    }
    

    这解决了我在屏幕上旋转加载程序被触发两次的问题。还有一点需要注意的是,这只对我测试过的 Android

    【讨论】:

    • 此解决方案可能有效,但与前面提到的 Alex Lockwood 存在相同的问题。
    【解决方案3】:

    我自己也遇到了同样的问题,没有好的解决方案。 它似乎是 Android 框架中的错误,这里是类似的线程,其中建议的解决方案是将 initLoader() 放在 onResume() 中 - 我已经尝试过它并且它有效,onLoadFinished() 只被调用一次: Android: LoaderCallbacks.OnLoadFinished called twice

    【讨论】:

      【解决方案4】:

      Android: LoaderCallbacks.OnLoadFinished called twice查看我的帖子

      在 ViewPager 中重新启动 Fragments 时,我遇到了类似的问题。我的解决方案是在完成加载程序后(在 onLoadFinished 结束时)通过调用删除加载程序

      getLoaderManager().destroyLoader(LOADER_ID);
      

      希望对你有帮助!

      【讨论】:

      • 这是一个非常糟糕的解决方案...销毁Loader 也会销毁与其关联的所有数据。 Loaders 的主要优点之一是数据在配置更改(例如方向更改等)时保留...销毁此数据意味着您需要在每次配置更改时重新查询数据。
      【解决方案5】:

      看起来像框架加载器错误的实现/错误。 1. 看看我从屏幕旋转后每个重要方法/回调的 Log.v(LOG_TAG, ...) 消息中得到了什么:

      ...: .initLoader() 100
      ...: onStartLoading()
      ...: onLoadFinished()
      ...: updateUi(); articles size=10
      ...: loadInBackground()
      ...: getInputStream() - HttpRequest
      ...: onLoadFinished()
      ...: updateUi(); articles size=10
      

      2. 正如你所见,'updateUi()' 之后的所有内容都不需要了。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2014-01-04
        • 2017-06-25
        • 2012-09-08
        • 2016-04-27
        • 2019-02-27
        • 1970-01-01
        • 2019-12-04
        • 2018-09-15
        相关资源
        最近更新 更多