当底层数据发生变化时,Cursorloader不会刷新

我有一个内容提供者,一个内容解析器和一个游标加载器。 加载器用于间接填充列表视图(即,不是简单的游标适配器,而是阵列适配器,因为我需要使用游标的结果来收集其他数据)。

当我更改基础数据时,由于未调用onLoadFinished(Loader<Cursor>, Cursor)回调函数,因此不会重新填充listview。

正如我在写这篇文章时所建议的那样,在这个问题上有很多问题。 例如CursorLoader在数据更改后不更新

所有的问题都指出了两件事:

  • 在你的内容提供者的query()方法中,你需要告诉游标关于通知a'la
  • c.setNotificationUri(getContext().getContentResolver(), uri);

  • 在您的内容提供者插入/更新/删除方法中,您需要通知URI:
  • getContext().getContentResolver().notifyChange(uri, null);

    我正在做这些事情。

    我也没有关闭任何我回来的游标。

    请注意,我的内容提供商位于单独的应用程序中(将其视为内容提供商应用程序 - 不启动主要活动)。 一个com.example.provider APK,com.example.app通过content://com.example.provider/table URI调用(在内容解析器中)。内容解析器(dbhelper)存在于一个库项目(com.example.appdb)活动链接。(这样,多个项目可以通过链接使用dbhelper,并且所有内容提供程序都通过单个APK安装)

    我已经打开了加载器管理器中的调试过程,并且可以看到数据更改后我强制刷新的位置(即加载器正在重新启动并且之前被标记为非活动状态),但没有任何内容会自动发生 - 而是响应我的力量刷新。

    任何想法为什么我的装载机没有被刷新?

    - 编辑 -

    加载器创建:

    Log.d(TAG, "onCreateLoader ID: " + loaderID);
    // typically a switch on the loader ID, and then 
    return dbHelper.getfoo()
    

    getfoo()返回一个游标加载器,通过:

    return new CursorLoader(context, FOO_URI, foo_Fields, foo_query, foo_argArray, foo_sort );

    装载程序完成需要光标并填充一个表格(并进行一些处理) - 没有什么特别的。

    public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) {
        Log.d(TAG, "onLoadFinished id: " + loader.getId());
        // switch on loader ID .. 
        FillTable(cursor, (FooAdapter) foo_info.listview.getAdapter();
    

    Loader Reset清除表格。

    public void onLoaderReset(Loader<Cursor> loader) {
        Log.d(TAG, "onLoaderReset id: " + loader.getId());
        // normally a switch on loader ID
        ((FooAdapter)foo_info.listview.getAdapter()).clear();
    

    内容提供者确实:

    公共游标查询(Uri uri,String []投影,字符串选择,String [] selectionArgs,String sortOrder){游标游标; SQLiteQueryBuilder qb = new SQLiteQueryBuilder();

        SQLiteDatabase db = dbHelper.getReadableDatabase();
    
        switch (sUriMatcher.match(uri)) {
        case FOO:
            qb.setTables(FOO);
            qb.setProjectionMap(FooProjectionMap);
            break; 
        default:
            throw new IllegalArgumentException("Unknown URI " + uri);
        }
    
        Cursor c = qb.query(db, projection, selection, selectionArgs, null, null, sortOrder);
    
        c.setNotificationUri(getContext().getContentResolver(), uri);
        return c;
    

    }

    然后插入/更新是类似的:

    public Uri insert(Uri uri, ContentValues initialValues) {
        ContentValues values;
        if (initialValues != null) {
            values = new ContentValues(initialValues);
        } else {
            values = new ContentValues();
        }
    
        String tableName;
        Uri contentUri;
    
        switch (sUriMatcher.match(uri)) {
        case FOO:
            tableName = FOOTABLE;
            contentUri = FOO_URI;
            break;
    
        default:
            throw new IllegalArgumentException("Unknown URI " + uri);
        }
    
        SQLiteDatabase db = dbHelper.getWritableDatabase();
        long rowId = db.insert(tableName, null, values);
        if (rowId > 0) {
            Uri objUri = ContentUris.withAppendedId(contentUri, rowId);
            getContext().getContentResolver().notifyChange(objUri, null);
            return objUri;
        }
    
        throw new SQLException("Failed to insert row into " + uri);
    }
    

    我看到你没有在onLoadFinished和onLoaderReset中调用swapCursor或changeCursor。 您需要为您的适配器来访问加载到新游标中的数据。

    在onLoadFinished中,调用如下所示:

    mAdapter.swapCursor(cursor)
    

    在onLoaderReset中,调用它来移除对旧游标的引用:

    mAdapter.swapCursor(null)
    

    mAdapter是你的listView的适配器。

    更多信息:http://developer.android.com/guide/components/loaders.html#onLoadFinished


    所以,对于看起来有问题的人有这个问题:

    确保你注册游标的URI和你通知游标的URI是相同的。

    在我的情况下,我使用了一个不同的URI来查询,而不是修改底层表的其他代码中使用的URI。 做出通知的工作并不容易,因此我一直将OnResume()中的加载器重置为解决方案。


    这不是对这个特定问题的直接回答,但可以帮助其他人处理类似的情况。 在我的情况下,我有一个连接,即使我在投影和查询中使用了完整的tablename.columnname。 无论如何,它最终会使用错误的ID值。 所以一定要检查你的ContentProvider或SQL语法。

    链接地址: http://www.djcxy.com/p/31993.html

    上一篇: Cursorloader not refreshing when underlying data changes

    下一篇: how to use join query in CursorLoader when its constructor does not support it