1

我有一个ListView使用AcitivityA名为. 适配器保存来自SimpleCursorAdapterRecipeAdapterSQLite

EditText顶部有一个视图ListView,用于在用户搜索食谱时过滤列表视图。当用户单击过滤后的项目时ListViewActivityB启动。

这一切都完美无缺。但是,当用户按下后退按钮恢复ActivityB时,我收到以下错误。

java.lang.IllegalStateException:
trying to requery an already closed cursor  android.database.sqlite.SQLiteCursor@418af170

我解决问题的尝试:

  • 将代码从 复制onCreate()onResume方法。
  • 添加c.requery()onResume()方法
  • 添加db.closeonDestroy()方法

谁能帮我解决我的问题?

这是我的代码:

在 中onCreatecursor填充ListView使用c.getCursor,当用户ListView通过过滤时EditTextc.getFilterCursor使用 。

public class RecipeActivity extends SherlockListActivity {

private DBHelper db = null;
private Cursor c = null;
private RecipeAdapter adapter = null;
ListView listContent;   
private EditText filterText = null;

@SuppressWarnings("deprecation")
@Override
public void onCreate(Bundle savedInstanceState) {
    try {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.filter_list);

        filterText = (EditText) findViewById(R.id.search_box);
        filterText.addTextChangedListener(filterTextWatcher);

        ListView listContent = getListView();

        db = new DBHelper(this);
        db.createDataBase();
        db.openDataBase();

        c = db.getCursor();         

        adapter = new RecipeAdapter(c);

        listContent.setAdapter(adapter);

        adapter.setFilterQueryProvider(new FilterQueryProvider() {
            public Cursor runQuery(CharSequence constraint) {
                // Search for states whose names begin with the specified letters.
                c = db.getFilterCursor(constraint);
                return c;
            }
        });

        startManagingCursor(c);


    } catch (IOException e) {
        e.printStackTrace();
    }
}




    private TextWatcher filterTextWatcher = new TextWatcher() {

    public void afterTextChanged(Editable s) {
    }

    public void beforeTextChanged(CharSequence s, int start, int count,
            int after) {
    }

    public void onTextChanged(CharSequence s, int start, int before,
            int count) {

        adapter.getFilter().filter(s);


    }

};

RecipeAdapter 内部类

class RecipeAdapter extends CursorAdapter {

    @SuppressWarnings("deprecation")
    public RecipeAdapter(Cursor c) {
        super(RecipeActivity.this, c);
    }

    public void bindView(View row, Context arg1, Cursor arg2) {
        RecipeHolder holder = (RecipeHolder) row.getTag();
        holder.populateFrom(c, db);

    }

    public View newView(Context arg0, Cursor arg1, ViewGroup arg2) {
        LayoutInflater inflater = getLayoutInflater();
        View row = inflater.inflate(R.layout.reciperow, arg2, false);
        RecipeHolder holder = new RecipeHolder(row);
        row.setTag(holder);

        return (row);
    }


static class RecipeHolder {
    public TextView id = null;
    private TextView name = null;
    private TextView desc = null;
    private TextView preptime = null;
    private TextView cooktime = null;
    private TextView serves = null;
    private TextView calories = null;
    private TextView fat = null;
    private TextView fav = null;

    RecipeHolder(View row) {
        id = (TextView) row.findViewById(R.id.id);
        name = (TextView) row.findViewById(R.id.recipe);
        desc = (TextView) row.findViewById(R.id.desc);
        preptime = (TextView) row.findViewById(R.id.preptime);
        cooktime = (TextView) row.findViewById(R.id.cooktime);
        serves = (TextView) row.findViewById(R.id.serving);
        calories = (TextView) row.findViewById(R.id.calories);
        fat = (TextView) row.findViewById(R.id.fat);
        fav = (TextView) row.findViewById(R.id.fav);
    }


    void populateFrom(Cursor c, DBHelper r) {
        id.setText(r.getId(c));
        name.setText(r.getRecipe(c));
        name.setTextColor(Color.parseColor("#CCf27c22"));
        desc.setText(r.getDesc(c));
        preptime.setText(r.getPrepTime(c) + ". ");
        cooktime.setText(r.getCookTime(c) + " mins");
        serves.setText(r.getServes(c));
        calories.setText(r.getCalories(c));
        fat.setText(r.getFat(c));
        fav.setText(r.getFav(c));

DBHelper 类中的 getCursor() 和 getFilterCursor() 代码

public Cursor getCursor() {
    SQLiteQueryBuilder queryBuilder = new SQLiteQueryBuilder();
    queryBuilder.setTables(DATABASE_TABLE);

    String[] columns = new String[] { KEY_ROWID, RECIPE, DESC, PREPTIME,
            COOKTIME, SERVES, CALORIES, FAT, CATEGORY, FAV };

    Cursor myCursor = queryBuilder.query(myDataBase, columns, null, null,
            null, null, RECIPE + " ASC");

    return myCursor;
}




public Cursor getFilterCursor(CharSequence constraint) {
    SQLiteQueryBuilder queryBuilder = new SQLiteQueryBuilder();
    queryBuilder.setTables(DATABASE_TABLE);

    String[] columns = new String[] { KEY_ROWID, RECIPE, DESC, PREPTIME,
            COOKTIME, SERVES, CALORIES, FAT, CATEGORY, FAV };

    if (constraint == null || constraint.length() == 0) {
        // Return the full list
        return queryBuilder.query(myDataBase, columns, null, null, null,
                null, RECIPE + " ASC");
    } else {
        String value = "%" + constraint.toString() + "%";

        return myDataBase.query(DATABASE_TABLE, columns, "RECIPE like ? ",
                new String[] { value }, null, null, null);
    }
}

完整的日志

FATAL EXCEPTION: main
java.lang.RuntimeException: Unable to resume activity {ttj.android.quorn/ttj.android.quorn.RecipeActivity}: 
java.lang.IllegalStateException: trying to requery an already closed cursor android.database.sqlite.SQLiteCursor@41954658
at android.app.ActivityThread.performResumeActivity(ActivityThread.java:2456)
at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:2484)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1185)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:137)
at android.app.ActivityThread.main(ActivityThread.java:4507)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:790)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:557)
at dalvik.system.NativeStart.main(Native Method)
Caused by: java.lang.IllegalStateException: trying to requery an already closed cursor android.database.sqlite.SQLiteCursor@41954658
at android.app.Activity.performRestart(Activity.java:4508)
at android.app.Activity.performResume(Activity.java:4531)
at android.app.ActivityThread.performResumeActivity(ActivityThread.java:2446)
4

1 回答 1

2

您运行应用程序的 Android 平台版本是什么?此方法 startManagingCursor 自 Honeycomb 以来已弃用。建议开发人员将新的 CursorLoader 类与 LoaderManager 一起使用,该类也可通过 Android 兼容性包在旧平台上使用。

实际上我在 Honeycomb 上遇到了同样的问题。但是我没有按照上面的说明进行操作,因为我没有太多时间来重写我的代码。所以这是我的解决方案,希望对您有所帮助。但是如果你有时间,你应该切换到使用 CursorLoader 和 LoaderManager 获得更好的性能。

@Override
protected void onResume() {
    super.onResume();
    //do the query again every time on resume
    Cursor c = mExpenseDb.queryCategories(mSettings.getCurrentAccount().getId());
    //mAdapter is a SimpleCursorAdapter, set its cursor to the new one 
    mAdapter.changeCursor(c);
}

@Override
protected void onPause() {
    super.onPause();
    //mAdapter is a SimpleCursorAdapter, invalidate its data and set it cursor to null on Activity pause
    mAdapter.notifyDataSetInvalidated();

    mAdapter.changeCursor(null);
}
于 2012-08-10T01:48:26.757 回答