ArrayIndexOutoutBoundsException thrown from ItemizedOverlay.getIndexToDraw
I have an Android app where I display a MapView with an ItemizedOverlay and where I want to allow users to touch the map to add new markers to the overlay. My onTouchEvent method uses an content provider to create a new item for the position touched. This calls populate(). When I touch the MapView for the first time the size method correctly returns 1 but I then get the ArrauIndexOutofBoundsException exception and no call to createItem method. Anyway so far I haven't discovered a solution. Here's the exception trace:
08-31 14:55:03.595: ERROR/AndroidRuntime(15897): java.lang.ArrayIndexOutOfBoundsException
08-31 14:55:03.595: ERROR/AndroidRuntime(15897): at com.google.android.maps.ItemizedOverlay.getIndexToDraw(ItemizedOverlay.java:211)
08-31 14:55:03.595: ERROR/AndroidRuntime(15897): at com.google.android.maps.ItemizedOverlay.draw(ItemizedOverlay.java:240)
08-31 14:55:03.595: ERROR/AndroidRuntime(15897): at uk.ac.aber.dcs.hiker_note.HikerNoteActivity$HikerNotesOverlay.draw(HikerNoteActivity.java:85)
08-31 14:55:03.595: ERROR/AndroidRuntime(15897): at com.google.android.maps.Overlay.draw(Overlay.java:179)
08-31 14:55:03.595: ERROR/AndroidRuntime(15897): at com.google.android.maps.OverlayBundle.draw(OverlayBundle.java:42)
08-31 14:55:03.595: ERROR/AndroidRuntime(15897): at com.google.android.maps.MapView.onDraw(MapView.java:530)
08-31 14:55:03.595: ERROR/AndroidRuntime(15897): at android.view.View.draw(View.java:6933)
08-31 14:55:03.595: ERROR/AndroidRuntime(15897): at android.view.ViewGroup.drawChild(ViewGroup.java:1646)
08-31 14:55:03.595: ERROR/AndroidRuntime(15897): at android.view.ViewGroup.dispatchDraw(ViewGroup.java:1373)
08-31 14:55:03.595: ERROR/AndroidRuntime(15897): at android.view.View.draw(View.java:6936)
08-31 14:55:03.595: ERROR/AndroidRuntime(15897): at android.view.ViewGroup.drawChild(ViewGroup.java:1646)
08-31 14:55:03.595: ERROR/AndroidRuntime(15897): at android.view.ViewGroup.dispatchDraw(ViewGroup.java:1373)
08-31 14:55:03.595: ERROR/AndroidRuntime(15897): at android.view.View.draw(View.java:6936)
08-31 14:55:03.595: ERROR/AndroidRuntime(15897): at android.widget.FrameLayout.draw(FrameLayout.java:357)
08-31 14:55:03.595: ERROR/AndroidRuntime(15897): at android.view.ViewGroup.drawChild(ViewGroup.java:1646)
08-31 14:55:03.595: ERROR/AndroidRuntime(15897): at android.view.ViewGroup.dispatchDraw(ViewGroup.java:1373)
08-31 14:55:03.595: ERROR/AndroidRuntime(15897): at android.view.ViewGroup.drawChild(ViewGroup.java:1644)
08-31 14:55:03.595: ERROR/AndroidRuntime(15897): at android.view.ViewGroup.dispatchDraw(ViewGroup.java:1373)
08-31 14:55:03.595: ERROR/AndroidRuntime(15897): at android.view.View.draw(View.java:6936)
08-31 14:55:03.595: ERROR/AndroidRuntime(15897): at android.widget.FrameLayout.draw(FrameLayout.java:357)
08-31 14:55:03.595: ERROR/AndroidRuntime(15897): at com.android.internal.policy.impl.PhoneWindow$DecorView.draw(PhoneWindow.java:1901)
08-31 14:55:03.595: ERROR/AndroidRuntime(15897): at android.view.ViewRoot.draw(ViewRoot.java:1530)
08-31 14:55:03.595: ERROR/AndroidRuntime(15897): at android.view.ViewRoot.performTraversals(ViewRoot.java:1266)
08-31 14:55:03.595: ERROR/AndroidRuntime(15897): at android.view.ViewRoot.handleMessage(ViewRoot.java:1868)
08-31 14:55:03.595: ERROR/AndroidRuntime(15897): at android.os.Handler.dispatchMessage(Handler.java:99)
08-31 14:55:03.595: ERROR/AndroidRuntime(15897): at android.os.Looper.loop(Looper.java:123)
08-31 14:55:03.595: ERROR/AndroidRuntime(15897): at android.app.ActivityThread.main(ActivityThread.java:3691)
08-31 14:55:03.595: ERROR/AndroidRuntime(15897): at java.lang.reflect.Method.invokeNative(Native Method)
08-31 14:55:03.595: ERROR/AndroidRuntime(15897): at java.lang.reflect.Method.invoke(Method.java:507)
08-31 14:55:03.595: ERROR/AndroidRuntime(15897): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:847)
08-31 14:55:03.595: ERROR/AndroidRuntime(15897): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:605)
08-31 14:55:03.595: ERROR/AndroidRuntime(15897): at dalvik.system.NativeStart.main(Native Method)
Here's the ItemizedOverlay subclass code:
private class HikerNotesOverlay extends ItemizedOverlay<OverlayItem> {
private int startX = -1;
private int startY = -1;
/**
* @param marker the push-pin
*/
public HikerNotesOverlay(Drawable marker) {
super(boundCenterBottom(marker));
populate();
}
/**
* @see com.google.android.maps.ItemizedOverlay#size()
*/
@Override
public int size() {
int size = 0;
// What's the size of the current cursor? There doesn't seem to be a row count request.
// Just get back ID field. Unfortunately this also returns a row for each
// record, but at least there is only one column
String [] projection = new String[]{"_ID"};
try{
Cursor hikerSizeCursor = managedQuery(HikerNote.Notes.CONTENT_URI, projection, null, null, null);
size = hikerSizeCursor.getCount();
if (size > 0) Log.i(LOG_TAG, "size: " + size);
//hikerSizeCursor.close();
}
catch(IllegalStateException ise){
Log.i(LOG_TAG, "size: ILLEGAL_STATE_EXCEPTION IGNORED");
}
return size;
}
@Override
public void draw(Canvas canvas, MapView mapView,
boolean shadow) {
Log.i(LOG_TAG, "draw");
super.draw(canvas, mapView, shadow);
}
/**
* @see com.google.android.maps.ItemizedOverlay#createItem(int)
*/
@Override
protected OverlayItem createItem(int i) {
Log.i(LOG_TAG, "createItem: " + i);
OverlayItem result = null;
// Get the item. We append the item id onto the URI
Uri noteUri = ContentUris.withAppendedId(HikerNote.Notes.CONTENT_URI, i);
Cursor itemCursor = managedQuery(noteUri, null, null, null, null);
if (itemCursor.moveToFirst()) {
// Should only be one item in the cursor
String comments = itemCursor.getString(HikerNote.COMMENT_COLUMN);
int lat = itemCursor.getInt(HikerNote.LATITUDE_COLUMN);
int lon = itemCursor.getInt(HikerNote.LONGITUDE_COLUMN);
result = new OverlayItem(new GeoPoint(lat, lon), HikerNote.Notes.NOTES_NAME, comments);
}
//itemCursor.close();
return result;
}
/**
* React to tap events on Map by showing an appropriate detail activity
*
* @see com.google.android.maps.ItemizedOverlay#onTap(com.google.android.maps.GeoPoint, com.google.android.maps.MapView)
*/
@Override
public boolean onTap(GeoPoint p, MapView mvMap1) {
// Do I need to do anything in here to display the overlay item's contents or will the superclass
// do this as default behaviour?
Log.i(LOG_TAG, "onTap");
return false; // Get the superclass to handle
}
@Override
public boolean onTouchEvent(MotionEvent event, MapView view){
// Touching the view gives us the chance to fire up the addNote activity
// so that we can add the note for the given position to the database
Log.i(LOG_TAG, "onTouchEvent");
boolean result = false;
final int action=event.getAction();
final int x=(int)event.getX();
final int y=(int)event.getY();
if (action==MotionEvent.ACTION_DOWN){
Log.i(LOG_TAG, "onTouchEvent: ACTION_DOWN. x= " + x + " y= " + y);
startX = x;
startY = y;
}
else if (action==MotionEvent.ACTION_UP) {
// Check to see if any intermediate points. If none then we have a straightforward
// touch without drag
Log.i(LOG_TAG, "onTouchEvent: ACTION_UP. x= " + x + " y= " + y);
if (x==startX && y==startY){
GeoPoint pt = mvMap.getProjection().fromPixels(x,y);
Log.i(LOG_TAG, "onTouchEvent: ACTION_UP. geopoint= " + pt);
// Now call the AddNote activity with extra geopoint information
Intent addNoteIntent = new Int开发者_Go百科ent(HikerNoteActivity.this, AddNote.class);
addNoteIntent.putExtra(AddNote.LOCATION_LATITUDE, pt.getLatitudeE6());
addNoteIntent.putExtra(AddNote.LOCATION_LONGITUDE, pt.getLongitudeE6());
HikerNoteActivity.this.startActivity(addNoteIntent);
result = true;
startX = -1;
startY = -1;
//setLastFocusedIndex(-1);
populate();
}
}
//return result || super.onTouchEvent(event, view);
return result;
}
}
Thanks
You probably should uncomment this line: //setLastFocusedIndex(-1); Whenever your list of elements change you should call setLastFocusedIndex(-1) before you call populate() It is documented here: http://groups.google.com/group/android-developers/browse_thread/thread/38b11314e34714c3
精彩评论