2012-01-30 113 views
4

我試圖通過使用Commonsware的Loader的適配器實現DataListFragment。這個Loader直接使用SQLiteDatabase,不需要使用ContentProvider。獲取SQLiteCursorLoader觀察數據更改

關於加載程序的android參考狀態: 「雖然加載程序處於活動狀態,但它們應監視其數據的來源並在內容更改時提供新的結果。」

在我的SQLiteCursor實現(下面)下,這不會發生。 OnLoadFinished()被調用一次,就是這樣。據推測,可以在底層數據庫發生變化的地方插入Loader.onContentChanged()調用,但通常數據庫代碼類不知道加載器,所以我不確定要實現這一點的最佳方式。

有沒有人有任何建議使加載器「數據意識」,或者我應該包裝數據庫的東西作爲一個ContentProvider和使用CursorLoader?

import com.commonsware.cwac.loaderex.SQLiteCursorLoader; 

public class DataListFragment extends ListFragment implements LoaderManager.LoaderCallbacks<Cursor>{ 

protected DataListAdapter mAdapter;  // This is the Adapter being used to display the list's data. 
public SQLiteDatabase  mSqlDb; 
private static final int LOADER_ID = 1; 

@Override 
public void onActivityCreated(Bundle savedInstanceState) { 
    super.onActivityCreated(savedInstanceState); 
    int rowlayoutID = getArguments().getInt("rowLayoutID"); 
    // Create an empty adapter we will use to display the loaded data. 
    // We pass 0 to flags, since the Loader will watch for data changes 
    mAdapter = new DataListAdapter(getActivity(),rowlayoutID, null , 0); 
    setListAdapter(mAdapter); 
    // Prepare the loader. Either re-connect with an existing one, 
    // or start a new one. 
    LoaderManager lm = getLoaderManager(); 
    // OnLoadFinished gets called after this, but never again. 
    lm.initLoader(LOADER_ID, null, this); 
} 
public Loader<Cursor> onCreateLoader(int id, Bundle args) { 
    String sql="SELECT * FROM "+TABLE_NAME+";"; 
    String[] params = null; 
    SQLiteCursorLoader CursorLoader = new SQLiteCursorLoader(getActivity(), mSqlDb, sql, params); 
    return CursorLoader; 
} 
public void onLoadFinished(Loader<Cursor> loader, Cursor data) { 
    // Swap the new cursor in. (The framework will take care of closing the old cursor once we return.) 
    mAdapter.swapCursor(data); 
    // The list should now be shown. 
    if (isResumed()) { setListShown(true);} 
    else { setListShownNoAnimation(true); } 
} 
public void onLoaderReset(Loader<Cursor> loader) { 
    // This is called when the last Cursor provided to onLoadFinished() 
    // above is about to be closed. We need to make sure we are no 
    // longer using it. 
    mAdapter.swapCursor(null); 
} 

回答

20

Loader文檔有缺陷。

內置於Android本身的Loader實現中的100%「監視其數據的來源並在內容更改時提供新的結果」。由於到目前爲止,Android本身內置的實現只有一個Loader,所以它們的文檔是準確的。

然而,引用我的書更新應該在一兩個小時被釋放:

中沒有任何需要此 行爲的框架。此外,在某些情況下,執行 顯然不是一個好主意 - 想象一個Loader將數據從Internet上加載,需要不斷輪詢某個服務器以查找更改。

我的計劃是增加SQLiteCursorLoader至少對數據庫更改有所瞭解,如果您通過它對所有數據庫修改進行路由。這也會有侷限性,因爲您不會在活動之間共享對象(更不用說可以從服務中訪問它們)。

CursorLoader這樣做的唯一原因是因爲它使用ContentProvider--因此可以知道所有操作的單例。

目前,無論代碼的哪一部分負責插入,更新和刪除,都需要點擊SQLiteCursorLoader並更新它,或者通知活動(例如,從Service),所以活動可以點擊肩膀上的SQLiteCursorLoader

+0

我一直在經歷Loader的源代碼,並且一直在懷疑。謝謝。 – CjS 2012-01-30 14:45:40

+0

對於我(我正在使用內容提供商)的工作解決方法是使用: 'getLoaderManager()。restartLoader(0,null,this);' – siefca 2012-07-18 22:46:36

+0

@ zx81如果您使用的是ContentProvider,那麼我不認爲你需要這樣做,相反,你應該通知加載器在你的URI邏輯中被改變了......不是嗎? – AutoM8R 2014-03-16 20:27:04