2012-08-10 4 views
1

이라는 사용자 정의 SimpleCursorAdapter을 사용하여 채워진 AcitivityAListView이 있습니다. 어댑터에는 데이터가 저장됩니다 SQLiteSimpleCursorAdapter가있는 안드로이드 ListView - 충돌 onResume

ListView 상단에는 사용자가 조리법을 검색 할 때 목록보기를 필터링하는 EditText보기가 있습니다. 사용자가 필터링 된 항목 ListView을 클릭하면 ActivityB이 시작됩니다.

이 모든 것이 완벽하게 작동합니다. 그러나 사용자가 ActivityB을 다시 시작하기 위해 backbutton을 누르면 다음 오류가 발생합니다. 이 문제를 해결에서

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

내 시도 :

  • onResume 방법에 onCreate()에서 코드를 복제.

사람이 내 문제를 도와 줄 수 db.close 방법 onDestroy()에 추가 onResume() 방법

  • c.requery()을 추가? cursorc.getCursor를 사용하여 ListView을 채우고 사용자가 EditText를 통해 ListView를 필터링 할 때 c.getFilterCursor가 사용되는 onCreate에서

    :

    여기 내 코드입니다.

    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()

    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 DBHelper 클래스 로그 캣

    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

    +0

    @Sam Logcat이 질문에 포함되었습니다. – tiptopjat

    +0

    onCreate()에서 데이터베이스를 열면 onDestroy()에 db.close()를 추가해야합니다. 'db.getCursor()'의 코드는 무엇입니까? – Sam

    답변

    2

    코드에서 Wha't 버전 안드로이드 플랫폼 당신은 당신의 응용 프로그램을 실행하고 있습니까? 이 메소드 startManagingCursor는 Honeycomb 이후 사용되지 않습니다. 개발자는 대신 새로운 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

    +0

    'android.database.CursorIndexOutOfBoundsException : 인덱스 -1이 요청되었으며 크기는 70'입니다. 내 목록에는 70 개의 항목이 있습니다. 나는'DBHelper.class'의'getCursor()'에'cursor.moveToFirst()'를 가지고 있지만 중지 예외가 발생합니다. – tiptopjat

    +0

    @tiptopjat 미안 해요, 출장 중이 었으니 제게 대답 할 기회가 없었어요. 여기 내 제안이있다. onCreate() 메서드에서 dbHelper 및 cursorAdaptor 초기화를 수행하고 ondb 쿼리를 수행하고 onResume() 메서드에서 커서를 변경합니다. CursorIndexOutOfBoundsException에 대해서는, cursor.moveToFirst()를 사전에 호출했을 경우는 발생하지 않습니다. 가능한 경우 업데이트 된 코드를 공유 할 수 있습니까? 감사. -어치 – Jay