【问题标题】:What's the mechanism of setNotificationUri?setNotificationUri 的机制是什么?
【发布时间】:2012-08-01 22:06:45
【问题描述】:

我刚刚实现了一个 CursorLoader,效果很好!事实上,我不相信我的 ListView 会在底层数据发生变化时自动更新,直到我测试它。这显然是 setNotificationUri 的魔力。

我的问题是,它如何知道游标中的数据何时发生了变化?假设我悄悄地在某处插入了一行。底层机制是否不断地查询数据库并与过去的数据进行比较?如果数据集很大,效率会不会非常低?

在我使用游标加载器之前,我会在必要时手动刷新。不用再这样做真是太好了,但是让 CursorLoader 在后台执行此操作是否有效?

【问题讨论】:

    标签: android android-cursorloader


    【解决方案1】:

    如果我在某处错了,请纠正我。

    ContentProviderquery(…) 方法中调用类似这样的方法:

    // Tell the cursor what uri to watch, so it knows when its source data changes
    cursor.setNotificationUri(getContext().getContentResolver(), uri);
    

    CursorLoader 返回光标并注册一个观察者。

    /* Runs on a worker thread */
    @Override
    public Cursor loadInBackground() {
        Cursor cursor = getContext().getContentResolver().query(mUri, mProjection,
                mSelection, mSelectionArgs, mSortOrder);
        if (cursor != null) {
            // Ensure the cursor window is filled
            cursor.getCount();
            registerContentObserver(cursor, mObserver);
        }
        return cursor;
    }
    
    /**
     * Registers an observer to get notifications from the content provider
     * when the cursor needs to be refreshed.
     */
    void registerContentObserver(Cursor cursor, ContentObserver observer) {
        cursor.registerContentObserver(mObserver);
    }
    

    当有人修改数据时,ContentProvider 会通知 ContentResolver 有关更改:

    getContext().getContentResolver().notifyChange(uri, null);
    

    ContentResolver 反过来通知所有注册的观察者。

    CursorLoader 注册的观察者强制它加载新数据。

    【讨论】:

    • 嗯...我没有在 Cursorloader 中编写任何上述代码。我只是在“onCreateLoader”中创建一个新的 cursorloader 并在“onLoadFinished”中交换新数据,如下所示:developer.android.com/guide/components/loaders.html 但我认为你是对的。 “notifyChange”语句告诉每个人某事发生了变化,系统自动知道它是否与任何给定的 uri 或游标相关。很整洁。
    • 即使我通过 SQLiteDatabase 而不是 ContentProvider 更新 db,CursorLoader 是否会重新启动?
    • @MarcinCzech:“即使我通过 SQLiteDatabase 而不是 ContentProvider 更新 db,CursorLoader 是否会重新启动?” - 不。您必须通过ContentProvider 进行所有更新,并且ContentProvider 必须进行适当的调用以绑定到观察者框架。
    • 通过阅读文档,我的理解是cursor.setNotificationUri(getContext().getContentResolver(), uri) 将导致给定 ContentResolver 上的任何侦听器在给定 uri 下的任何内容为 notifyChange()d 时得到通知。但是,解析器上没有任何侦听器,因为它是从上下文中新鲜出来的。你是说作为一种不可见的副作用,它更新了光标中的一些内部状态?
    • @f470071:“第二个更改数据并调用 notifyChange()”——我没有说 activity 调用 notifyChange()。我说ContentProvider 调用notifyChange()。第二个活动应该是使用ContentProvider 来更改ContentProvider 中的数据,而ContentProvider 是调用notifyChange() 的那个。
    猜你喜欢
    • 2020-05-24
    • 1970-01-01
    • 1970-01-01
    • 2011-03-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-07-22
    • 2015-05-28
    相关资源
    最近更新 更多