-1

我正在使用內容提供者來存儲和檢索數據庫中的數據。這是用戶安裝應用程序時在應用程序中發生的事情。使用內容提供者從數據庫加載數據

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

下面是當用戶啓動應用程序第一次發生了什麼。我也添加了評論。

@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

錯誤!有一些我錯過了。我花時間在這個問題上到處找,然後我走進文件,我發現這種方法

/** 
* 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底層數據時,它會通知contentresolver有關更改。 由於CursorLoader不會自動檢測數據變化,我們需要使用setNotificationUri(ContentResolver cr, Uri uri);

我希望這會幫助別人。 :)