Issue
I've got a problem with my map app. I'm populating the map overlays inside an asynctask. They are added to the mapview in the ui-thread.
The problem occurs when I zoom the map and add new points afterwards, which triggers the computation of these points to be displayed. I'm getting an arrayindexoutofboundsexception
inside the android class method viewroot.draw
whenever I execute this pattern (open map, zoom, add points).
The populating asynctask also calls populate()
on my itemized_overlay
implementation after adding all points. It's doinbackground-method
returns and I get the mentioned exception immediately afterwards. It doesn't run the onpostexecution-method
, which should follow. If the mapview isn't touched, I can add as many points as I like. When the error occurs the overlay icons disappear except for their shadows before the debugger stops the application.
Thread [<1> main] (Suspended (exception ArrayIndexOutOfBoundsException))
ViewRoot.draw(boolean) line: 1457
ViewRoot.performTraversals() line: 1167
ViewRoot.handleMessage(Message) line: 1764
ViewRoot(Handler).dispatchMessage(Message) line: 99
Looper.loop() line: 143
ActivityThread.main(String[]) line: 5068
Method.invokeNative(Object, Object[], Class, Class[], Class, int, boolean) line: not available [native method]
Method.invoke(Object, Object...) line: 521
ZygoteInit$MethodAndArgsCaller.run() line: 858
ZygoteInit.main(String[]) line: 616
NativeStart.main(String[]) line: not available [native method]
Any ideas?
Edit: added code
the asynctask:
package de.***.android.memo_neu;
import java.util.HashMap;
import java.util.Iterator;
import android.app.ProgressDialog;
import android.content.Context;
import android.database.Cursor;
import android.os.AsyncTask;
import android.util.Log;
import com.google.android.maps.OverlayItem;
public class PunkteZeigen_Tab_AsyncTask extends
AsyncTask<Cursor, Integer, Object> {
private PunkteZeigen_Tab_Liste context_liste;
private PunkteZeigen_Tab_Karte context_karte;
private ProgressDialog progress_fortschritt;
private int int_modus;
public static final int LISTE = 0;
public static final int KARTE = 1;
private static final int PROGRESS_SET_MIN = 0;
private static final int PROGRESS_UPDATE = 1;
private static final int PROGRESS_SET_MAX = 2;
private static final int PROGRESS_MAX = 3;
public PunkteZeigen_Tab_AsyncTask(Object con, int int_mod) {
int_modus = int_mod;
switch (int_modus) {
case LISTE:
context_liste = (PunkteZeigen_Tab_Liste) con;
break;
case KARTE:
context_karte = (PunkteZeigen_Tab_Karte) con;
break;
default:
}
}
protected void onPreExecute() {
switch (int_modus) {
case LISTE:
progress_fortschritt = new ProgressDialog((Context) context_liste);
progress_fortschritt
.setTitle(R.string.punktezeigen_tab_liste_asynctask_progressdialog_title);
break;
case KARTE:
progress_fortschritt = new ProgressDialog((Context) context_karte);
progress_fortschritt
.setTitle(R.string.punktezeigen_tab_karte_asynctask_progressdialog_title);
break;
default:
}
progress_fortschritt.setCancelable(false);
progress_fortschritt.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
progress_fortschritt.show();
Log.d("memo_debug", "onPreExecute fertig");
}
protected void onProgressUpdate(Integer... int_progress) {
switch (int_progress[0]) {
case PROGRESS_SET_MIN:
progress_fortschritt.setProgress(int_progress[1]);
break;
case PROGRESS_UPDATE:
if (int_progress[1] >= 0) {
if ((int_progress[1] % 5) == 0) {
progress_fortschritt
.incrementProgressBy(progress_fortschritt.getMax() / 5);
}
} else {
progress_fortschritt.incrementProgressBy(-int_progress[1]);
}
break;
case PROGRESS_SET_MAX:
progress_fortschritt.setMax(int_progress[1]);
break;
case PROGRESS_MAX:
progress_fortschritt.setProgress(progress_fortschritt.getMax());
break;
default:
}
}
protected Object doInBackground(Cursor... cursor_db_anfrage) {
progress_fortschritt.setMax(cursor_db_anfrage[0].getCount());
switch (int_modus) {
case LISTE:
return listeBearbeiten(cursor_db_anfrage[0]);
case KARTE:
return karteBearbeiten(cursor_db_anfrage);
default:
return -1;
}
}
private int listeBearbeiten(Cursor cursor_db_anfrage) {
if (cursor_db_anfrage.moveToFirst()) {
GeoPunkt geopkt_geopunkt = new GeoPunkt();
HashMap<String, Object> hashmap_liste_daten_datum;
do {
// geopkt_geopunkt.id= cursor_db_anfrage.getInt(0);
geopkt_geopunkt.name = cursor_db_anfrage.getString(1);
geopkt_geopunkt.lat = cursor_db_anfrage.getInt(2);
geopkt_geopunkt.lon = cursor_db_anfrage.getInt(3);
geopkt_geopunkt.icon = cursor_db_anfrage.getInt(4);
hashmap_liste_daten_datum = new HashMap<String, Object>(2);
hashmap_liste_daten_datum.put("geopkt_name",
geopkt_geopunkt.name);
hashmap_liste_daten_datum.put("geopkt_lat_lon", "Lat:"
+ Integer.toString(geopkt_geopunkt.lat) + " " + "Lon:"
+ Integer.toString(geopkt_geopunkt.lon));
hashmap_liste_daten_datum.put("geopkt_icon",
geopkt_geopunkt.icon);
context_liste.memosingleton_anwendung.list_liste_daten
.add(hashmap_liste_daten_datum);
publishProgress(PROGRESS_UPDATE,
cursor_db_anfrage.getPosition());
} while (cursor_db_anfrage.moveToNext());
}
return cursor_db_anfrage.getCount();
}
private HashMap<Integer, ItemOverlay_neu> karteBearbeiten(
Cursor... cursor_db_anfrage) {
// cursor_db_anfrage[0] geopkt, cursor_db_anfrage[1] icon
// temporaere hashmap fuer overlays (sammlung von punkten) die der
// karte hinzugefuegt werden.
HashMap<Integer, ItemOverlay_neu> hashmap_itemoverlays_temp = new HashMap<Integer, ItemOverlay_neu>();
// falls neue punkte vorhanden sind
if (cursor_db_anfrage[0].moveToFirst()) {
ItemOverlay_neu itemoverlay_temp;
GeoPunkt geopkt_geopunkt = new GeoPunkt();
OverlayItem overlayitem_temp;
// fuer alle gefundenen symbole
if (cursor_db_anfrage[1].moveToFirst()) {
do {
// erzeuge overlay mit zugeordnetem symbol
itemoverlay_temp = new ItemOverlay_neu(context_karte
.getResources().getDrawable(
cursor_db_anfrage[1].getInt(0)),
context_karte);
// falls in der hashmap des singletons noch kein overlay mit
// diesem symbol vorhanden ist, fuege es hinzu
if (!context_karte.memosingleton_anwendung.hashmap_itemoverlays
.containsKey(cursor_db_anfrage[1].getInt(0))) {
context_karte.memosingleton_anwendung.hashmap_itemoverlays
.put(cursor_db_anfrage[1].getInt(0),
itemoverlay_temp);
}
// fuege das overlay in die temporaere hashmap ein
hashmap_itemoverlays_temp.put(
cursor_db_anfrage[1].getInt(0), itemoverlay_temp);
// hashmap aus dem singleton speichert alle overlays mit den
// entsprechenden geopunkten, temporaere hashmap speichert
// nur neue geopunkte
} while (cursor_db_anfrage[1].moveToNext());
}
Log.d("memo_debug", "erste while do fertig");
// fuer alle erfassten neuen punkte
do {
// geopkt_geopunkt.id = cursor_db_anfrage.getInt(0);
geopkt_geopunkt.name = cursor_db_anfrage[0].getString(1);
geopkt_geopunkt.lat = cursor_db_anfrage[0].getInt(2);
geopkt_geopunkt.lon = cursor_db_anfrage[0].getInt(3);
geopkt_geopunkt.icon = cursor_db_anfrage[0].getInt(4);
// erzeuge overlayitem (geopunkt mit zusaetzlichen daten) zum
// einfuegen in overlays
overlayitem_temp = new OverlayItem(
geopkt_geopunkt.getGeoPoint(), geopkt_geopunkt.name, "");
// fuege neue punkte zur singleton hashmap und zur temporaeren
// hashmap hinzu
itemoverlay_temp = context_karte.memosingleton_anwendung.hashmap_itemoverlays
.get(geopkt_geopunkt.icon);
itemoverlay_temp.addOverlay(overlayitem_temp);
itemoverlay_temp = hashmap_itemoverlays_temp
.get(geopkt_geopunkt.icon);
itemoverlay_temp.addOverlay(overlayitem_temp);
publishProgress(PROGRESS_UPDATE,
cursor_db_anfrage[0].getPosition());
} while (cursor_db_anfrage[0].moveToNext());
Log.d("memo_debug", "zweite while do fertig");
publishProgress(PROGRESS_MAX, 0);
// ruft populate() fuer die overlays auf, um sie spaeter anzeigen zu
// koennen
Iterator<ItemOverlay_neu> iterator_itemoverlays = context_karte.memosingleton_anwendung.hashmap_itemoverlays
.values().iterator();
publishProgress(PROGRESS_SET_MIN, 0);
publishProgress(PROGRESS_SET_MAX,
context_karte.memosingleton_anwendung.hashmap_itemoverlays
.size());
while (iterator_itemoverlays.hasNext()) {
iterator_itemoverlays.next().initialisieren();
publishProgress(PROGRESS_UPDATE, -1);
}
Log.d("memo_debug", "erstes populate fertig");
publishProgress(PROGRESS_MAX, 0);
iterator_itemoverlays = hashmap_itemoverlays_temp.values()
.iterator();
publishProgress(PROGRESS_SET_MIN, 0);
publishProgress(PROGRESS_SET_MAX, hashmap_itemoverlays_temp.size());
while (iterator_itemoverlays.hasNext()) {
iterator_itemoverlays.next().initialisieren();
publishProgress(PROGRESS_UPDATE, -1);
}
Log.d("memo_debug", "zweites populate fertig");
publishProgress(PROGRESS_MAX, 0);
}
Log.d("memo_debug", "karteBearbeiten fertig");
return hashmap_itemoverlays_temp;
}
protected void onPostExecute(Object obj_result) {
Log.d("memo_debug", "onPostExecute gestartet");
switch (int_modus) {
case LISTE:
context_liste.listeAnzeigen((Integer) obj_result);
break;
case KARTE:
context_karte.karteAnzeigen(
(HashMap<Integer, ItemOverlay_neu>) obj_result,
PunkteZeigen_Tab_Karte.ANZEIGEN);
break;
default:
}
progress_fortschritt.setProgress(progress_fortschritt.getMax());
progress_fortschritt.dismiss();
Log.d("memo_debug", "onPostExecute fertig");
}
}
Methods that start the asynctask and are called after it finishes:
private void dbAbfrageStarten() {
SQLiteDatabase sqldb_zugriff = sqldb_db_verwaltung
.getReadableDatabase();
// select * from tabellenname where zeit>x
Cursor cursor_db_anfrage_geopkt = sqldb_zugriff.query(
SQL_DB_Verwaltung.TABELLEN_NAME,
null,
"zeit >"
+ Long.toString(memosingleton_anwendung
.letzterDBZugriff(MemoSingleton.KARTE)), null,
null, null, null);
// select icon from tabellenname groupby icon
// erfasse symbole die den ausgelesenen punkten zugeordnet wurden
Cursor cursor_db_anfrage_icon = sqldb_zugriff.query(
SQL_DB_Verwaltung.TABELLEN_NAME,
new String[] { SQL_DB_Verwaltung.NAME_SPALTE_5 }, null, null,
SQL_DB_Verwaltung.NAME_SPALTE_5, null, null);
PunkteZeigen_Tab_AsyncTask asynctask_dbabfrage = new PunkteZeigen_Tab_AsyncTask(
this, PunkteZeigen_Tab_AsyncTask.KARTE);
asynctask_dbabfrage.execute(cursor_db_anfrage_geopkt,
cursor_db_anfrage_icon);
Log.d("memo_debug", "dbAbfrageStarten fertig");
}
public void karteAnzeigen(
HashMap<Integer, ItemOverlay_neu> hashmap_itemoverlays_temp,
int int_modus) {
Log.d("memo_debug", "karteAnzeigen punkt1");
// erfasse, zur zeit auf der karte angezeigte, overlays
MapView mapview_karte = (MapView) this
.findViewById(R.id.punktezeigen_karte_layout_mapview_neu);
List<Overlay> list_karten_overlay = mapview_karte.getOverlays();
memosingleton_anwendung.aktualisiereDBZugriff(MemoSingleton.KARTE);
Iterator<ItemOverlay_neu> iterator_itemoverlays;
Log.d("memo_debug", "karteAnzeigen punkt2");
switch (int_modus) {
case ANZEIGEN:
iterator_itemoverlays = hashmap_itemoverlays_temp.values()
.iterator();
break;
case WIEDERHERSTELLEN:
iterator_itemoverlays = memosingleton_anwendung.hashmap_itemoverlays
.values().iterator();
break;
default:
iterator_itemoverlays = null;
}
Log.d("memo_debug", "karteAnzeigen punkt3");
while ((iterator_itemoverlays != null)
&& iterator_itemoverlays.hasNext()) {
list_karten_overlay.add(iterator_itemoverlays.next());
}
// zeichne die karte neu
mapview_karte.invalidate();
Log.d("memo_debug", "karteAnzeigen fertig");
}
memosingleton_anwendung
is an instance of application where i store some data.
Edit further investigation:
I further investigated the problem and it seems to originate from the use of the memosingleton_anwendung.hashmap_itemoverlays
. If i don't add points to these overlays the app works flawlessly. It seems that populate()
runs in a separate thread and can't handle changes in the list although i'm calling it after adding all points.
Solution
The solution to my problem included storing the computed overlays in an ArrayList<Overlay>
instead of storing objects of my ItemizedOverlay
-Implementation.
Answered By - vendetta
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.