【问题标题】:How do I use a CursorLoader to show individual database records one by one如何使用 CursorLoader 逐一显示单个数据库记录
【发布时间】:2012-01-03 03:22:02
【问题描述】:

我正在尝试创建一个ContentProvider,每条记录都包含一个问题和相应的答案。以及显示每个问题和答案的 TextView 的 Activity 以及这些 TextView 下方的“下一步”按钮。单击下一步按钮时,我希望显示下一个问题和答案。

我正在尝试使用 CursorLoader 和 LoaderManager,因为 CursorLoader 将它们的数据保存在 onStop()onStart() 之间,我正在尝试了解 CursorLoadersLoaderManagers

我找到的示例都使用setListAdapter(),但我不希望我的活动看起来像一个列表。我试图通过使用SimpleCursorAdapter 并在我的main.xml 布局中使用bindView() 来解决这个问题。不确定这是否可行。

如果我有一个普通的光标,我会使用moveToNext(),但对于LoaderManager,我似乎必须使用restartLoader() 进行新查询。我认为创建一个新查询比简单地使用游标转到下一条记录要花费更多时间。特别是因为我必须知道当前或下一条记录的位置。

所以我的问题是:我可以使用CursorLoaderLoaderManager 逐条记录地浏览数据库,而不必为下一条记录进行新的查询吗?还是 CursorLoadersLoaderManagers 真的只适用于 ListViews?

到目前为止,这是我的代码,我意识到它并不多,但我已经阅读并重新阅读了有关 Loaders 和 LoadManagers 的 Android 页面。

 public class Main extends Activity implements LoaderManager.LoaderCallbacks<Cursor>{

SimpleCursorAdapter adapter;
String curFilter;

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);

    this.adapter = new SimpleCursorAdapter(getApplicationContext(),
                                           R.layout.main,
                                           null,
                                           new String[]{},
                                           new int[]{R.id.questionText,R.id.answerText},
                                           0);
    LinearLayout mainLayout = (LinearLayout)findViewById(R.id.mainLayout);

    this.adapter.bindView(mainLayout, getApplicationContext(), null);

    this.getLoaderManager().initLoader(0,null, this);

    Button nextQuestionButton = (Button)this.findViewById(R.id.Nextbutton);

    nextQuestionButton.setOnClickListener(new OnClickListener() {
        @Override
        public void onClick (View v) {
        }               
    });
}

【问题讨论】:

    标签: android android-loadermanager


    【解决方案1】:

    我知道我的问题很模糊,我真的很迷茫。几个月后,这是我的回答,希望它对我过去职位的人有所帮助。

    onCreateLoader() 在我调用 getLoaderManager().initLoader() 或内容提供者发生更改时自动调用(内容提供者必须调用 getContentResolver().notifyChange() 才能工作)。我提供了在覆盖方法 LoaderManager.LoaderCallbacks.onCreateLoader() 时制作光标加载器的代码。光标加载器会自动交给 onLoadFinished()。就是这样,我不再触摸光标加载器。自动调用的 onLoadFinished() 接收一个游标(由游标加载器生成)作为参数。我使用游标参数 this.adapter.setCursor(cursor) 在我的 onLoadFinished() 覆盖中更新了适配器。

    SimpleCursorAdapter 没有 moveToNext 或 moveToPrevious,所以我做了一个 SteppedAdapter,见下图:

    public class SteppedAdapter {
        private Cursor cursor = null;
        // This class uses a reference which may be changed
        // by the calling class.
        public SteppedAdapter (Cursor cursor) {
        this.cursor = cursor;
        }
    
        private int getColumnIndexOrThrow (String columnName) {
        return cursor.getColumnIndexOrThrow(columnName);
        }   
    
        public void moveToNext () {     
        if (null != cursor && !cursor.isClosed()) {
            if (cursor.isLast()) {
                cursor.moveToFirst();
            }
            else {
                cursor.moveToNext();
            }
        }   
        }
    
        public void moveToPrevious () {
        if (null != cursor && !cursor.isClosed()) {
            if (cursor.isFirst()) {
                cursor.moveToLast();
            }
            else {
                cursor.moveToPrevious();
            }
        }
        }
    
        public String getCurrentTarget (String targetColumn) throws EmptyCursorException {
        int idx = cursor.getColumnIndex(targetColumn);  
        String value = null;
        try {
            value = cursor.getString(idx);  
        }
        catch (CursorIndexOutOfBoundsException e){
            if ( 0 == cursor.getCount()) {
                throw new EmptyCursorException("Cursor is empty: "+e.getMessage()); 
            }
            else {
                throw e;
            }
        }
        return value;
        }   
    
        public void setCursor (Cursor cursor) {
        this.cursor = cursor;
        }
    
        public void setCursorToNull () {
        this.cursor = null; 
        }
    
        public int getPosition () {
        return this.cursor.getPosition();
        }
    
        public boolean cursorIsClosed () {
        return this.cursor.isClosed();
        }   
    
        public int getCount () {
        return cursor.getCount();
        }
    } // end
    

    因为适配器在 onLoadFinished() 中使用方法 adapter.setCursor(Cursor) 设置,并在 onLoaderReset() 中使用方法 adapter.setCursorToNull() 清除。那么适配器必须有这些方法。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-09-20
      • 1970-01-01
      • 1970-01-01
      • 2015-08-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多