2012-01-30 109 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