2012-08-10 74 views
1

我有一個ListViewAcitivityA這是填充使用自定義SimpleCursorAdapter調用RecipeAdapter。適配器保存來自SQLite的數據Android ListView with SimpleCursorAdapter - 崩潰onResume

ListView的頂部有一個EditText視圖,用於在用戶搜索配方時過濾列表視圖。當用戶點擊已過濾的ListView中的項目時,ActivityB開始。

這一切都完美。但是,當用戶按下後退按鈕以恢復ActivityB時,出現以下錯誤。

java.lang.IllegalStateException: 
trying to requery an already closed cursor [email protected] 

我在解決了這個問題的嘗試:

  • 複製從onCreate()代碼到onResume方法。
  • 添加c.requery()onResume()方法
  • 添加db.closeonDestroy()方法

誰能幫助我與我的問題?

這裏是我的代碼:

onCreate,該cursor使用c.getCursor填充ListView當用戶通過過濾的EditTextListView,使用c.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)); 

getCursor()和getFilterCursor()從DBHelper類

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); 
    } 
} 

FULL logcat的

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 [email protected] 
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 [email protected] 
at android.app.Activity.performRestart(Activity.java:4508) 
at android.app.Activity.performResume(Activity.java:4531) 
at android.app.ActivityThread.performResumeActivity(ActivityThread.java:2446) 
+0

請發佈您的所有LogCat錯誤並指出最後一個錯誤發生的位置。 – Sam 2012-08-10 00:36:37

+0

@Sam Logcat現在包括在內。 – tiptopjat 2012-08-10 00:52:27

+0

由於您在onCreate()中打開數據庫,因此您應該在onDestroy()中添加'db.close()'。 'db.getCursor()'的代碼是什麼? – Sam 2012-08-10 01:03:43

回答

2

代碼Wha't的版本Android平臺你正在運行你的應用程序?自Honeycomb以來,此方法startManagingCursor已棄用。建議開發人員將新的CursorLoader類與LoaderManager一起使用,而通過Android兼容性包,舊版平臺也可以使用該類。

其實我在蜂窩上遇到了同樣的問題。但是我沒有按照上面的說明操作,因爲我沒有太多時間來重寫我的代碼。所以這裏是我的解決方案,我希望它有幫助。但是如果你有時間的話,你應該改用使用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); 
} 
+0

今晚我回到家時,我會給你一個鏡頭。我應該修改我的'onCreate()'嗎? – tiptopjat 2012-08-10 09:10:14

+0

我得到一個錯誤'android.database.CursorIndexOutOfBoundsException:索引-1請求,大小爲70'。我的清單有70個項目。我在'DBHelper.class'的'getCursor()'中有'cursor.moveToFirst()',但是發生了停止異常。 – tiptopjat 2012-08-10 19:30:20

+0

@tiptopjat對不起,我出差了,所以我沒有機會回答你的問題。這是我的建議。在onCreate()方法中執行dbHelper和cursorAdaptor初始化,並在onResume()方法中執行do db查詢和更改光標。關於CursorIndexOutOfBoundsException,如果事先調用cursor.moveToFirst(),則不應該發生。如果可能,你可以分享你更新的代碼嗎?謝謝。 -Jay – Jay 2012-08-15 07:01:40