2016-12-23 55 views
1

Fabric向我報告這個錯誤,所以我真的不知道它是什麼時候以及如何造成的。也許用戶停止在訪問DB應用...RuntimeException對cursor.getCount()

的代碼是:

private void addOrUpdateJoinTable(SQLiteDatabase db, long site_id, JSONArray myJSONCategoriesArray) throws JSONException { 

    ContentValues newCategoriesValues = new ContentValues(); 
    Cursor cursor = null; 

    try { 
     for (int i = 0; i < myJSONCategoriesArray.length(); i++) { 

      JSONObject jsCategory = myJSONCategoriesArray.getJSONObject(i); 

      cursor = db.rawQuery(
        "SELECT " + 
          SitesDBOpenHelper.DATABASE_SITES_CATEGORIES_TABLE + "." + SitesDBOpenHelper.KEY_ID + ", " + 
          SitesDBOpenHelper.DATABASE_SITES_TABLE + "." + SitesDBOpenHelper.KEY_ID + " AS S_id, " + 
          SitesDBOpenHelper.DATABASE_CATEGORIES_TABLE + "." + SitesDBOpenHelper.KEY_ID + " AS C_id " + 
          " FROM " + 
          SitesDBOpenHelper.DATABASE_SITES_TABLE + 
          " INNER JOIN " + 
          SitesDBOpenHelper.DATABASE_SITES_CATEGORIES_TABLE + " ON " + 
          SitesDBOpenHelper.DATABASE_SITES_CATEGORIES_TABLE + "." + SitesDBOpenHelper.KEY_SITE_ID + " = S_id " + 
          " INNER JOIN " + 
          SitesDBOpenHelper.DATABASE_CATEGORIES_TABLE + " ON " + 
          "C_id = " + 
          SitesDBOpenHelper.DATABASE_SITES_CATEGORIES_TABLE + "." + SitesDBOpenHelper.KEY_CATEGORY_ID + 
          " WHERE " + 
          "S_id = ?" + 
          " AND " + 
          SitesDBOpenHelper.DATABASE_CATEGORIES_TABLE + "." + SitesDBOpenHelper.KEY_CODE + " = ?", 
        new String[] {Long.toString(site_id), jsCategory.get(SitesDBOpenHelper.KEY_CODE).toString()} 
      ); 


      if ((cursor != null) && (cursor.getCount() > 0)) { 

       cursor.moveToFirst(); 

       long id = cursor.getLong(cursor.getColumnIndex(SitesDBOpenHelper.KEY_ID)); 

       newCategoriesValues.put(SitesDBOpenHelper.KEY_SITE_ID, cursor.getLong(cursor.getColumnIndex("S_id"))); 
       newCategoriesValues.put(SitesDBOpenHelper.KEY_CATEGORY_ID, cursor.getLong(cursor.getColumnIndex("C_id"))); 

       result = db.update(SitesDBOpenHelper.DATABASE_SITES_CATEGORIES_TABLE, newCategoriesValues, SitesDBOpenHelper.KEY_ID + " = ?", new String[]{Long.toString(id)}); 

       if (debug) Log.d(Constants.APP_TAG, "update " + newCategoriesValues.toString()); 
      } else { 

       String resultSites_columns[] = new String[] { 
         SitesDBOpenHelper.KEY_ID, 
         SitesDBOpenHelper.KEY_CODE, 
       }; 

       String where = SitesDBOpenHelper.KEY_CODE 
         + " = ?"; 

       String whereArgs[] = {jsCategory.get(SitesDBOpenHelper.KEY_CODE).toString()}; 

       cursor = db.query(SitesDBOpenHelper.DATABASE_CATEGORIES_TABLE, resultSites_columns, where, whereArgs, null, null, null); 

       if ((cursor != null) && (cursor.getCount() > 0)) { 

        //dumpCursor(cursor); 

        cursor.moveToFirst(); 

        newCategoriesValues.put(SitesDBOpenHelper.KEY_SITE_ID, site_id); 

        newCategoriesValues.put(SitesDBOpenHelper.KEY_CATEGORY_ID, cursor.getLong(cursor.getColumnIndex(SitesDBOpenHelper.KEY_ID))); 

        db.insert(SitesDBOpenHelper.DATABASE_SITES_CATEGORIES_TABLE, null, newCategoriesValues); 

        if (debug) Log.d(Constants.APP_TAG, "insert " + newCategoriesValues.toString()); 
       } else { 

        if (debug) Log.d(Constants.APP_TAG, "!! category not found !! " + jsCategory.get(SitesDBOpenHelper.KEY_CODE).toString()); 

       } 

      } 
     } 

    } catch (NumberFormatException e) { 
     if (debug) Log.d(Constants.APP_TAG, "NumberFormatException " + e); 
    }catch (SQLiteException e) { 
     if (debug) Log.d(Constants.APP_TAG, "SQLLiteException " + e); 
    } finally { 
     if (cursor != null) { 
      cursor.close(); 
     } 
    } 
} 

的錯誤是:

Fatal Exception: java.lang.RuntimeException: An error occured while executing doInBackground() 
     at android.os.AsyncTask$3.done(AsyncTask.java:300) 
     at java.util.concurrent.FutureTask.finishCompletion(FutureTask.java:355) 
     at java.util.concurrent.FutureTask.setException(FutureTask.java:222) 
     at java.util.concurrent.FutureTask.run(FutureTask.java:242) 
     at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:231) 
     at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112) 
     at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587) 
     at java.lang.Thread.run(Thread.java:818) 
Caused by android.database.CursorWindowAllocationException: Cursor window allocation of 2048 kb failed. # Open Cursors=649 (# cursors opened by this proc=649) 
     at android.database.CursorWindow.<init>(CursorWindow.java:108) 
     at android.database.AbstractWindowedCursor.clearOrCreateWindow(AbstractWindowedCursor.java:198) 
     at android.database.sqlite.SQLiteCursor.fillWindow(SQLiteCursor.java:139) 
     at android.database.sqlite.SQLiteCursor.getCount(SQLiteCursor.java:133) 
     at com.my.example.LoadSitesListTask.addOrUpdateJoinTable(LoadSitesListTask.java:1461) 
     at com.my.example.LoadSitesListTask.updateDBFromJSONData(LoadSitesListTask.java:1152) 
     at com.my.example.LoadSitesListTask.doInBackground(LoadSitesListTask.java:153) 
     at com.my.example.LoadSitesListTask.doInBackground(LoadSitesListTask.java:58) 
     at android.os.AsyncTask$2.call(AsyncTask.java:288) 
     at java.util.concurrent.FutureTask.run(FutureTask.java:237) 
     at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:231) 
     at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112) 
     at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587) 
     at java.lang.Thread.run(Thread.java:818) 

誰能告訴我這種類型的錯誤的東西嗎? 如果用戶在工作時停止應用程序,這是「正常」嗎?或者是否有可能防止這種情況?

無論如何,一件奇怪的事情是爲遊標請求的2048 kb的分配。 您可以看到,基於包含2個整數的resultSites_columns,2048 kb沒有意義。

這是否意味着什麼?

+0

您確定關閉了光標嗎? –

+0

@user yes我是,這段摘錄在一個大的try/catch中,遊標在'finally'中被關閉。而這場撞車事故是我見過的第一次。 – 2ndGAB

+0

你寫了cursor.moveToFirst(); ? – Godwin

回答

0

問題是遊標沒有關閉。您在try-finally塊內有一個循環,但問題是您打開了myJSONCategoriesArray.length()遊標,但只關閉最後一個,即在循環的最後一次迭代中分配給cursor的那個遊標。

你需要做的是移動的循環內的try-finally塊:

for (int i = 0; i < myJSONCategoriesArray.length(); i++) { 
    Cursor cursor = db.rawQuery(/* rest omitted */); 
    try { 
     // Use the cursor 
    } finally { 
     if (cursor != null) cursor.close(); 
    } 
} 

這樣,你將關閉所有遊標,而不僅僅是最後一個。

+0

Gloups!你是對的。 – 2ndGAB