问题
I am using an Array List to store data about moving objects on screen. I suspect this is because my renderer and my logic are running on separate threads, but sometimes when data is removed from the list I get an indexOutOfBoundsException. I have taken all the steps I can think of to avoid this including try/catch but the exception still sometimes occurs. This is the part of my renderer thread that seems to cause the exception.
public void drawMobs(GL10 gl) {
boolean playing = MyLaunchActivity.getPlaying();
if(playing == true){
try{
ArrayList<String> mobDat = Play.getMobDat();
while (currentLoadSpace < mobDat.size()){
if(!mobDat.isEmpty() || currentLoadSpace < mobDat.size()){
loadObject = mobDat.get(currentLoadSpace);
float loadCoordX = Float.parseFloat(mobDat.get(currentLoadSpace + 2));
float loadCoordY = Float.parseFloat(mobDat.get(currentLoadSpace + 3));
/*some rendering*/
currentLoadSpace+=4;
}
}
}catch( ArrayIndexOutOfBoundsException e){ Log.d(TAG, "caught");}
currentLoadSpace = 0;
}}
as you can see I have tried a few things but the error still occurs. Here is the error log
01-02 14:02:42.650: E/AndroidRuntime(6947): FATAL EXCEPTION: GLThread 10
01-02 14:02:42.650: E/AndroidRuntime(6947): java.lang.IndexOutOfBoundsException: Invalid index 23, size is 20
01-02 14:02:42.650: E/AndroidRuntime(6947): at java.util.ArrayList.throwIndexOutOfBoundsException(ArrayList.java:255)
01-02 14:02:42.650: E/AndroidRuntime(6947): at java.util.ArrayList.get(ArrayList.java:308)
01-02 14:02:42.650: E/AndroidRuntime(6947): at basicmelon.games.agameofsorts.LoadLevel.drawMobs(LoadLevel.java:530)
01-02 14:02:42.650: E/AndroidRuntime(6947): at basicmelon.games.agameofsorts.MyGLSurfaceRenderer.onDrawFrame(MyGLSurfaceRenderer.java:82)
01-02 14:02:42.650: E/AndroidRuntime(6947): at android.opengl.GLSurfaceView$GLThread.guardedRun(GLSurfaceView.java:1429)
01-02 14:02:42.650: E/AndroidRuntime(6947): at android.opengl.GLSurfaceView$GLThread.run(GLSurfaceView.java:1184)
回答1:
One possible solution could be:
http://docs.oracle.com/javase/6/docs/api/java/util/concurrent/CopyOnWriteArrayList.html
If this is not an option, you could use synchronized(yourList) {} to prevent concurent modifications.
回答2:
Your code is inconsistent and is rather faulty. For example why do you test twice the same condition? (currentLoadSpace < mobDat.size()
)
Secondly, your error is coming from :
mobDat.get(currentLoadSpace + 3)
You're searching for index of 23 when mobDat
only contains 21 elements.
So you should check that the following lines are actually less than mobDat.size()
:
currentLoadSpace + 2
and
currentLoadSpace + 3
回答3:
I think you have to synchronize the access to your ArrayList. ArrayList is not thread safe. To catch the IndexOutOfBoundsException is bad design. This exception should be avoided by your code.
回答4:
You need to check for the arraylist size. The removed postion should not be greater than size oflist
You need to do somthing like the following
void avoidArrayIndexOutOfBounds(int position, ArrayList listOfdata){
if(position>(listOfdata.size()-1)){
position = listOfdata.size()-1;
}
}
回答5:
Note also that you're checking that currentLoadSpace is smaller than mobDat.size(), but you're trying to retrieve from currentLoadSpace+3 (which, as far as this piece of code is concerned, may well be out of bounds).
回答6:
I know there is already an answer, but try simply catching an IndexOutOfBoundsException
instead of an ArrayIndexOutOfBoundsException
I suggest this because you`re catching the Array exception and still getting the standard Index exception. This is most likely due to the fact that Index is a "higher/lower" (however you want to see it) exception than the Array exception. Meaning that you did indeed catch the Array exception, but beyond that the Index one is still being thrown.
来源:https://stackoverflow.com/questions/8701861/avoiding-index-out-of-bounds-exceptions