2012-07-14 118 views
1

我遇到了一個很奇怪的異常。它在這裏運行良好,但我的客戶不斷遇到這個異常,然後崩潰,它花了我很多小時才弄明白,但不幸的是迄今爲止還沒有運氣,任何幫助將不勝感激!奇怪的ArrayIndexOutOfBoundsException

這是代碼:

protected void onPostExecute(List<File> result) { 
    try { 
     mBooks.clear(); 
     if (result != null) { 
      ArrayList<BookInfo> newBooks = new ArrayList<BookInfo>(); 
      for (File f : result) { 
       BookInfo bi = new BookInfo(BookCollections.this, f); 
       if (!contains(bi)) { 
        newBooks.add(bi); 
       } 
      } 
      mDB.insertBooks(newBooks); 
      mBooks.addAll(newBooks); 
      new AlertDialog.Builder(BookCollections.this) 
        .setTitle(newBooks.size() + " Books found!") 
        .setPositiveButton(android.R.string.ok, null) 
        .setView(
      new BookInfoList(BookCollections.this, 
      newBooks)).show(); 
     } 
    } catch (Exception e) { 
     e.printStackTrace(); 
    } finally { 
     mScanDlg.dismiss(); 
     notifyDataSetChanged(); 
    } 
} 

private boolean contains(BookInfo bi) { 
    if (bi == null) { 
     return true; 
    } 
    for (BookInfo book : mBooks) { 
     if (book.equalTo(bi)) { 
      return true; 
     } 
    } 
    for (FolderInfo fi : mFolders) { 
     if (fi.getBooks() != null) { 
      for (BookInfo book : fi.getBooks()) { 
       if (book.equalTo(bi)) { 
        return true; 
       } 
      } 
     } 
    } 
    return false; 
} 

請幫助我。由於

此異常(java.lang.ArrayIndexOutOfBoundsException)籌集最多

for (File f : result) { 
    BookInfo bi = new BookInfo(BookCollections.this, f); 
    if (!contains(bi)) { 
     newBooks.add(bi); 
    } 
} 
+1

添加廣泛的日誌記錄或發明一種方法來獲得調用堆棧的時候發生這種情況... – user1494736 2012-07-14 05:16:47

+0

你說它在這裏工作得很好。這裏有什麼?你重新創建了這個問題嗎?如果是的話,你可以發佈calltrace的logcat輸出嗎? – 2012-07-14 05:56:09

回答

3

之間,我注意到你的方法名是onPostExecute。這可能是一個處理Web請求的方法嗎?如果是這樣,那麼當你的客戶運行這個代碼時,它可能在一個多線程的Web容器中運行。但是,您的收藏ArrayList不是線程安全的集合。這可能是它在開發(單線程)環境中工作的原因,但不在繁忙的服務器上。

考慮使用Collections.synchronizedList()方法來實例化ArrayList。請務必遵循API文檔中有關在同步塊內迭代的建議。

+1

我懷疑它是由多線程引起的,我檢查了所有使用mBooks和mFolders的地方,所有這些地方都在UI線程中。我試過: 保護無效onPostExecute(名單結果){ \t \t \t \t如果(結果!= NULL){ \t \t \t \t \t列表 LST = Collections.synchronizedList(結果); \t \t \t \t \t ArrayList newBooks = new ArrayList (); \t \t \t \t \t的(文件f:LST){ \t \t \t \t \t \t 它還是失敗了。 – sleepcry 2012-07-14 05:38:47

+0

恐怕我第一次沒有仔細閱讀你的代碼。您指出在迭代作爲輸入參數傳遞的集合時會發生問題。我在評論錯誤的東西(ArrayList )。看來,列表集合可能會改變你下。 Android運行時是否將它傳遞給你? (我不瞭解Android知道這一點)。如果您可以重現這一點,請添加一個try-catch塊來捕獲異常並打印該消息。看看哪個索引導致問題會很有趣。 – pglezen 2012-07-14 06:34:28

0

同樣奇怪的行爲,我前幾天在模擬器的應用展示perfact數據,但在設備它顯示了一個錯誤相同的概念作爲一個ArrayList我的建議是從你的PostExecute的刪除此行如果u有沒有面對在ArrayList中mBooks這個任何內容前添加

mBooks.clear(); // remove this line 

,並建立和清理項目它爲u必須面臨同樣的問題,不同的ArrayList和理清這樣

是的,你是右側y我們的錯誤出現在登錄這個

for (File f : result) { 
         BookInfo bi = new BookInfo(BookCollections.this, f); 
         if (!contains(bi)) { 
          newBooks.add(bi); 
         } 
        } 

首先檢查你的ArrayList大小

Log.d("Size",""+newBooks.size()); 

如果大於0比感覺烏爾陣列和一件事是

改變你的方法包含 bcz accroding到您的如果條件數據插入newBooks數組當返回數據時包含方法是我認爲你總是讓布爾值因此對於檢查

在登錄

Log.d("BooleanValue",""+newBooks.size()); 

如果(前!包含(BI))從日誌輸出 condtion你能看到的數據插入ArrayList的或不按條件成立

+0

嗨汗,發生異常時,沒有這樣的行:mBooks.clear();我在調試之後添加了這個。對不起。這條線是否重要? mBooks arraylist之前已經有了一些東西,這就是爲什麼我檢查if(!contains(bi)){ – sleepcry 2012-07-14 05:50:51

0

這最終發現這是在

BookInfo bi = new BookInfo(BookCollections.this, f); 

產生一個普通ArrayIndexOutOfBoundsException因爲有一個索引超出邊界的子句。

0
  1. 因爲您有「mBooks.clear();」在onPoseExecute()的第一行,語句

    for (BookInfo book : mBooks) { 
        if (book.equalTo(bi)) { 
         return true; 
        } 
    } 
    

    在似乎就沒有任何意義。

  2. 您確定與「FoldInfo fi」相關的書籍不會在外面更改嗎?

    for (FolderInfo fi : mFolders) { 
         if (fi.getBooks() != null) { 
          for (BookInfo book : fi.getBooks()) { 
           if (book.equalTo(bi)) { 
            return true; 
           } 
          } 
         } 
        } 
    

    我認爲下面的代碼可以更好:

    for (FolderInfo fi : mFolders) { 
        ArrayList<BookInfo> books = fi.getBooks(); 
        if (books != null) { 
         for (BookInfo book : books) { 
          if (book.equalTo(bi)) { 
           return true; 
          } 
         } 
        } 
    } 
    
  3. 當你正在使用的AsyncTask和一些代碼(不是這個postexecute)在不同的線程中運行,最好是考慮使用一些鎖以保護您的mBooksmFolders或許mDB