使用CursorLoader在ListFragment中查询SQLite数据库的最佳实践是什么?

44
我在我的项目中使用了Android兼容库。我按照DevGuide(http://developer.android.com/reference/android/app/Fragment.html)中的描述设置了ListFragment,并使用了一个简单的CursorLoader,这个CursorLoader是由Christian编写的,可以不使用内容提供程序 (不使用ContentProvider使用CursorLoader)。
问题是,在我的ListFragment/父Activity中,我应该在哪里打开数据库,返回Cursor,创建适配器并设置ListAdapter呢?
因此,在我的应用程序中,我有TitlesFragment、DetailsFragment、FragmentLayoutActivity和DetailsLayoutActivity。
最好的做法是...
在ListFragment的onActivityCreated中打开数据库,在ListFragment的onDestroy中关闭它,就像下面的代码示例一样。
@Override
public void onActivityCreated(Bundle savedInstanceState) {
    super.onActivityCreated(savedInstanceState);
    // Open database
    playersDatabaseHelper = new PlayersDBAdapter(getActivity());
    playersDatabaseHelper.open();
    getLoaderManager().initLoader(0, null, this);
    ...
}

@Override
public void onDestroy() {
    super.onDestroy();
    if (playersDatabaseHelper != null) {
        playersDatabaseHelper.close();
    }
}
  • onCreateLoader中查询数据库并返回游标,然后在onLoadFinished中创建适配器并设置列表适配器,就像下面的代码示例一样

  • @Override
    public Loader<Cursor> onCreateLoader(int id, Bundle args) {
        // Now create and return a CursorLoader that will take care of
        // creating a Cursor for the data being displayed.
        return new MyCursorLoader(getActivity()) {
            @Override
            public Cursor loadInBackground() {
                playersCursor = playersDatabaseHelper.getAllPlayers();
                return playersCursor;
            }
        };
    
    }
    
    @Override
    public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) {      
        // Create an empty adapter we will use to display the loaded data.
        playersAdapter = new RowAdapter(getActivity(), playersCursor, R.layout.players_overview_row);
    
        // Allocate the adapter to the List displayed within this fragment.
        setListAdapter(playersAdapter);
    
        playersAdapter.swapCursor(cursor);
    
        // The list should now be shown.
        if (isResumed()) {
            setListShown(true);
        } else {
            setListShownNoAnimation(true);
        }
    }
    

    我是否在正确的方向上,或者应该将它们中的一些移动到其他地方?感谢您的时间!


    有人能否请评论我的问题。 - micadelli
    所以你有没有得到答案?我惊讶于你有14个赞,但并没有真正的答案。 - kpierce8
    1个回答

    6

    抱歉我对CursorLoader和Fragment没有经验,但是我已经在不同线程和活动中并发访问的情况下使用了SQLiteOpenHelper。

    我会假设PlayersDBAdapter在内部使用SQLiteOpenHelper类。但您的open()和close()方法正在做什么并不清楚?

    我所做的:

    • 将您的SQLiteOpenHelper定义为“应用程序”范围的单例,而不是像您所做的那样是活动范围的
    • 在Application onCreate中实例化SQLiteOpenHelper单个实例
    • 不要在任何activity onDestroy中释放SQLiteOpenHelper实例,因为当一个activity停止时,另一个activity可能仍需要打开数据库
    • 我想SQLiteOpenHelper实例应该在application onTerminate中清除(不确定,因为onTerminate实际上几乎从不被调用)
    • 我有DBAdapter对象,它通过mySQLiteOpenHelper.getWritableDatabase()获得一个SQLiteDatabase引用
    • 这些DBAdapter通常在activity onCreate中分配,并在onDestroy中释放

    至少这个方法可以运行,在拥有数千个用户的应用程序中没有崩溃。欢迎提出改进建议 :-)


    1
    这确实是一个好的解决方案。我已经在我的四个应用程序中使用了这种方法,它非常有效。在Android 2.2及以下版本中偶尔会出现错误,但在2.3+版本中它非常有效。 - Srichand Yella
    我的应用程序兼容Android 1.5及以上版本,我没有任何例外。只是在某些特定设备上遇到了罕见的“SQLiteDiskIOException:磁盘I / O错误”,但我认为这可能与SD卡访问或类似问题有关。 - Thierry

    网页内容由stack overflow 提供, 点击上面的
    可以查看英文原文,
    原文链接