1

相当noobish和我在这里的第一篇文章。我有一个在 2.3.3 中运行良好的应用程序,它使用自定义 baseadapter 填充列表视图。问题是我正在使用 Android 3/4 中已弃用的 startManagingCursor 和 requery。

我正在使用 sqlite 和一个数据库适配器,它包含我的所有查询和一个私有方法来从活动传递参数。您可以通过长按某个项目或单击某个项目以在新活动中打开它并在您成功返回列表更新时更新列表。

我知道我们不应该在主 UI 上运行这些类型的操作,但我无法弄清楚 cursorloader 并且我什至需要它吗?我是否应该使用 asynctask 之类的其他东西在不同的线程上运行。我只是不明白这一切是如何结合在一起的,任何朝着正确方向的帮助将不胜感激。谢谢。

这是我认为最相关的代码来自 MyActivity 的一个小样本

public class MyActivity extends ListActivity {

private MyDBAdapter dbAdapter;
private MyCursorAdapter mCursorAdapter;

@Override
    public void onCreate(Bundle savedInstanceState) {          

        super.onCreate(savedInstanceState); 
        setContentView(R.layout.mylayout);

    this.dbAdapter = new MyDBAdapter(this);
        this.dbAdapter.open();

    queryParams = getQueryParams();
    queryDB(queryParams);
}

private void queryDB(String qParams) {
    Cursor c = this.dbAdapter.fetchQuery(qParams);
    startManagingCursor(c);
        this.mCursorAdapter = new MyCursorAdapter(this, c);
        setListAdapter(this.mCursorAdapter);
        this.mCursorAdapter.changeCursor(c);
    }

public void updateStatus(long paramLong, int paramInt) {
    Cursor c = this.dbAdapter.updateDBStatus(paramLong, paramInt);
    startManagingCursor(c);
    this.mCursorAdapter.changeCursor(c);
}

@Override
protected void onDestroy() {
    super.onDestroy();
    if (this.dbAdapter != null) {
    this.dbAdapter.close();
    }
}
}

和 CursorAdapter

public class MyCursorAdapter extends CursorAdapter {

public MyCursorAdapter(Context cxt, Cursor cur, int flags) {
        super(cxt, cur);
        mContext = cxt;
        mLayoutInflater = LayoutInflater.from(cxt); 
    }

    @Override
    public View newView(Context cxt, Cursor cur, ViewGroup parent) {
        View vw = mLayoutInflater.inflate(LAYOUT_ID, parent, false);
        return vw;
    }

    @Override
    public void bindView(View vw, Context cxt, Cursor cur) {

        int id = cur.getInt(cur.getColumnIndexOrThrow("_id"));
        String name = cur.getString(cur.getColumnIndexOrThrow("name"));
    int completed = cur.getInt(cur.getColumnIndexOrThrow("completed"));

    TextView tv = (TextView) vw.findViewById(R.id.name);

    if(completed == 1) {
        tv.setTextColor(0x7fffffff);
        } else {
        tv.setTextColor(0xffffffff);
        }
    }
}

================ 编辑==================

我最终删除了 startManagingCursor() 和 requery() 并从兼容性包中添加了 import android.support.v4.widget.CursorAdapter 。由于我从不同位置多次调用,我创建了一个私有 Cursor mCursor 并使用 this.mCursorAdapter.changeCursor(mCursor) 来更新它。

现在这几乎可以工作,除了:

  1. 你真的不应该这样做,因为它仍然在主 UI 上运行
  2. 关闭光标取决于应用程序的设置方式

就我而言,我无法关闭光标,否则我的列表视图将为空。在 onDestroy() 中关闭它不能保证运行,并且在 onBackPressed() 中关闭它不起作用,因为您可以单击一个列表项,该列表项使用新光标打开一个新活动。当有人单击列表项然后单击后退按钮时,列表应该在同一个位置,因此关闭 onStop()(并在 onStart() 中打开)也不是答案。我也在所有活动中尝试了一个公共静态游标,但这也有问题。我没有尝试的另一件事是将光标信息立即加载到内存中,然后立即关闭它,但这似乎不太理想。

我真的很喜欢 CursorLoader 的想法,除了它只接受一个 URI 并且你需要一个内容提供者并且它不接受 rawQuery()。我的数据库中有数千个项目,并且使用我的数据库适配器进行了一百个不同类型的查询调用,而重新更改所有这些似乎是一件很痛苦的事情。我认为 CursorLoader 是最好的方法,但我对 android 实现它的方式感到失望。

我还看到有人写的没有 ContentProvider 的 CursorLoader使用 AsyncTaskLoader,因此您不需要 ContentProvider。这可能是我现在最好的选择,但其他人指出没有刷新数据更改的机制。我将不得不调查一下。

4

0 回答 0