【问题标题】:Load data from db using content provider使用内容提供程序从数据库加载数据
【发布时间】:2017-02-26 07:47:35
【问题描述】:

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

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

问题是第一次在 db 中没有任何数据,直到服务下载数据并存储它。发生这种情况时,CursorLoader 不会从 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;
    }

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

@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 一些指导将不胜感激。

【问题讨论】:

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


    【解决方案1】:

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

    /**
     * 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 方法中添加了对此方法的调用。 这是我的提供商提供的一些 sn-p

     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);

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-09-17
      • 2023-03-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-09-03
      相关资源
      最近更新 更多