在正在管理的Loader上调用stopLoading实际上是不安全的吗?

时间:2014-01-15 22:48:22

标签: android android-cursorloader

Loader#stopLoading()的Android文档说:

  

在LoaderManager中使用Loader时,必须不要调用此方法   你自己,或者你会对Loader的管理产生冲突。

但这是真的吗?具体来说,我对CursorLoader感兴趣。我通过Android源代码查看了4.2版本,看起来非常温和。有没有人尝试过使用这种方法并看到了问题?如果我想保持当前活动Cursor最后由CursorLoader传递,并且由于内部ContentObserver被触发而暂时停止重新加载,是否有替代方法?基本上我想对ContentProvider进行一系列更改,这是对这个托管Cursor的源代码,我不希望Loader在完成之前开始大量的负载。

2 个答案:

答案 0 :(得分:1)

我同意a.ch依赖Android源代码的方式并不是因为您冒着使用未来更新破坏应用程序的风险,而且因为Android的数百个修改版本(碎片化的乐趣) )。 stopLoading()无论如何都不会起作用,原因见下文。

cancelLoad()不会关闭底层游标(你从哪里得到它?)所以虽然这个方法会在一个正在进行时取消一个加载,但它不会阻止未来的加载。即使它会阻止未来的加载它也不会起作用(出于同样的原因,stopLoading()将无效)。

我最初想要解决这个问题的方法是实现一个自定义的CursorLoader,并使用一个标志覆盖onContentChanged()方法,以决定是否“接受”更改。这样可以暂时禁用更新:

class MyCursorLoader extends CursorLoader {
    private boolean mDontUpdate;

    public MyCursorLoader(Context context, Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
        super(context, uri, projection, selection, selectionArgs, sortOrder);
    }

    @Override
    public void onContentChanged () {
        if (! mDontUpdate) {
            super.onContentChanged();
        }
    }

    @Override
    public boolean takeContentChanged () {
        return mDontUpdate ? false : super.takeContentChanged();
    }

    void dontUpdate(boolean dontUpdate) {
        mDontUpdate = dontUpdate;
    }
}

您可以在onCreateLoader(int,Bundle)中使用此类而不是CursorLoader,并在数据库更新期间设置不更新标志。

现在它的效果很好,但事实并非如此。虽然从问题中不清楚CursorLoader和结果Cursor的用途我假设Cursor用于ListView或类似小部件的CursorAdapter。 小部件将自己的ContentObserver注册到Cursor并相应地更新视图。因此,即使没有加载新的Cursor,ListView(GridView或附加到Cursor的任何其他小部件)仍然会更新(Android会在CursorAdapter中调用newView,bindView方法)。

这让我想到了我的下一个方法。 虽然从你的问题不清楚,我假设你正在对数据库进行一些修改?如果是这种情况那么为什么不在一次交易中进行所有修改呢?如果在一个事务中完成,则在事务提交之前,任何地方都不会显示更改,这可能就是您想要的。

如果你的Cursor没有数据库支持,你可能不得不在更新期间从你的小部件中删除适配器。

答案 1 :(得分:0)

首先,你不应该依赖android源代码:如果当前的android构建没有任何问题,那并不意味着将来不会有任何问题。我建议将android系统视为一个黑盒子,这样可以让你编写健壮可靠的应用程序。

根据您对替代方案的提问,请考虑cancelLoad()