使用内容提供程序

时间:2017-02-26 07:47:36

标签: android android-contentprovider android-contentresolver android-cursorloader android-loadermanager

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

  1. App启动一项服务,该服务将从服务器和商店下载数据 它在db
  2. 应用正在使用CursorLoader从db
  3. 加载数据

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

    这就是我使用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一些指导意见将不胜感激。

1 个答案:

答案 0 :(得分:2)

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

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()CursorLoader对URI基础数据进行任何更改时,它会通知内容解析器有关更改的信息。 由于setNotificationUri(ContentResolver cr, Uri uri);不会自动检测数据更改,因此我们需要使用delimiter

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