2012-07-14 99 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