使用内容提供程序从数据库加载数据

Load data from db using content provider

我正在使用内容提供程序从数据库中存储和检索数据。这是用户安装应用程序时应用程序中发生的情况。

  1. 应用程序启动一个服务,该服务将从服务器下载数据并存储 它在 db
  2. 应用程序正在使用 CursorLoader 从 db
  3. 加载数据

问题是第一次在服务下载数据并存储之前数据库中没有任何数据。当发生这种情况时,CursorLoader 不会从数据库加载数据。如果我关闭并重新打开应用程序,它确实会从数据库加载数据。

我就是这样使用的ContentProvider

@Override
public int bulkInsert(Uri uri, ContentValues[] values) {
    final SQLiteDatabase db = feederDbHelper.getWritableDatabase();
    int match = sUriMatcher.match(uri);
    switch (match) {
        case CODE_INSERT_SOURCE:
            //Return the number of rows inserted from our implementation of bulkInsert
            return insertRecords(FeederContract.SourceEntry.TABLE_NAME, db, values, uri);
        case CODE_INSERT_ARTICLE:
            return insertRecords(FeederContract.ArticleEntry.TABLE_NAME, db, values, uri);
        default:
            return super.bulkInsert(uri, values);
    }
}

这是insertRecords方法

public int insertRecords(String tabbleName, SQLiteDatabase db, ContentValues[] values, Uri uri) {
        db.beginTransaction();
        int rowsInserted = 0;
        try {
            for (ContentValues value : values) {
                long _id = db.insertWithOnConflict(tabbleName, null, value, SQLiteDatabase.CONFLICT_REPLACE);
                if (_id != -1) {
                    rowsInserted++;
                }
            }
            db.setTransactionSuccessful();
        } finally {
            db.endTransaction();
        }

        if (rowsInserted > 0) {
            getContext().getContentResolver().notifyChange(uri, null);
        }
        //Return the number of rows inserted from our implementation of bulkInsert
        return rowsInserted;
    }

这是用户第一次启动应用程序时发生的情况。我也添加了评论。

@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
    View view = inflater.inflate(R.layout.feeds_fragment, container, false);
    ButterKnife.bind(this, view);
    loadAd();
    initRc();
    // Starting service to download feeds
    FeederSyncUtil.startSync(getActivity());
    // Starting loader to load feeds
    getActivity().getSupportLoaderManager().initLoader(ID_FEEDS_LOADER, null, this); 
    return view;
}

这些是装载机callbacks

@Override
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
    return new CursorLoader(getActivity(),
            FeederContract.ArticleEntry.CONTENT_URI,
            MAIN_FEED_PROJECTION,
            null,
            null,
            null);
}

@Override
public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
    Log.d(TAG, data.getCount() + "");
    mFeedsAdapter.swapCursor(data);
}

@Override
public void onLoaderReset(Loader<Cursor> loader) {
    mFeedsAdapter.swapCursor(null);
}

我在这里错过了什么?尽管我正在使用 getContext().getContentResolver().notifyChange(uri, null) 但它仍然没有刷新 Cursor 一些指导将不胜感激。

错了!我缺少一些东西。我花了几个小时在这个问题上到处寻找然后我进入文档并找到了这个方法

/**
 * Register to watch a content URI for changes. This can be the URI of a specific data row (for 
 * example, "content://my_provider_type/23"), or a a generic URI for a content type.
 * 
 * @param cr The content resolver from the caller's context. The listener attached to 
 * this resolver will be notified.
 * @param uri The content URI to watch.
 */
void setNotificationUri(ContentResolver cr, Uri uri);

然后我在我的提供者的 query 方法中添加了对此方法的连接调用。 这是我的提供商的一些片段

 public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
        int match = sUriMatcher.match(uri);
        Cursor cursor = null;
        switch (match) {
            case CODE_INSERT_SOURCE:
                cursor = feederDbHelper.getReadableDatabase().query(FeederContract.SourceEntry.TABLE_NAME,
                        projection,
                        selection,
                        selectionArgs,
                        null,
                        null,
                        sortOrder);
                break;
            case CODE_VIEW_ARTICLE:

                cursor = feederDbHelper.getReadableDatabase().query(FeederContract.ArticleEntry.TABLE_NAME,
                        projection,
                        selection,
                        selectionArgs,
                        null,
                        null,
                        sortOrder);
                break;

            default:
                throw new UnsupportedOperationException("Unknown uri " + uri);
        }
        cursor.setNotificationUri(getContext().getContentResolver(),uri);
        return cursor;
    }

所以这一行cursor.setNotificationUri(getContext().getContentResolver(),uri); 做所有的魔术。当使用 insert()delete()update()bulkInsert() 的 URI 基础数据发生任何更改时,它会通知内容解析器有关更改。 由于 CursorLoader 不会自动检测数据变化,我们需要使用 setNotificationUri(ContentResolver cr, Uri uri);

我希望这会对某人有所帮助。 :)