Ich habe ein seltsames Problem, das ich hoffe, ich kann es gut genug erklären. Meine App hat zwei Aktivitäten - MainActivity und SearchActivity. Ich habe eine Schaltfläche auf MainActivity, die einen Upload von der Datenbank auf dem Gerät in eine entfernte Datenbank auf meinem Webserver auslöst. Wenn ich beim ersten Start der App auf die Schaltfläche klicke, funktioniert das problemlos. Wenn ich zur SearchActivity wechsle, nichts tue und zurückwechsle, dann versuche die Schaltfläche, die App stürzt mit einer ConcurrentModificationException ab. Ich habe eine AsyncTask, die den Inhalt einer lokalen Datenbank sendet (bereits aus der Datenbank herausgezogen und über die Parameter als ArrayList an den Thread gesendet). Ich habe Stunden damit verbracht, das zu debuggen und kann immer noch nicht herausfinden, wo es ist. Irgendwelche Vorschläge würden sehr geschätzt werden.ConcurrentModificationException in Android AsyncTask
Dies ist der Code auf dem Button drücken, ausgelöst, um die Inhalte der Datenbank von einem separaten Databaser Thread
Button btnRemoteSync = (Button)findViewById(R.id.btnSync);
btnRemoteSync.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent startUpload = new Intent(getString(R.string.broadcast_search_database));
startUpload.putExtra("type-id",1);
LocalBroadcastManager.getInstance(getApplicationContext()).sendBroadcast(startUpload);
}
});
Dies ist der Code in den BroadcastReceiver zu verlangen, das jede Antwort von dem databaser bekommt und fügt sie zu einer ArrayList von benutzerdefinierten ResponseObjects. Wenn der Database-Thread einen Bssid-Wert von DONE sendet, wird die AsyncTask mit der als Parameter übergebenen ArrayList gestartet.
@Override
public void onReceive(Context context, Intent intent) {
String bssid = intent.getStringExtra(getString(R.string.data_bssid));
if (bssid.equals("DONE")) {
RemoteDatabaseUploader rdb = new RemoteDatabaseUploader(getApplicationContext());
rdb.execute(databases);
} else {
databases.add(new ResponseObject(getApplicationContext(),
bssid,
intent.getStringExtra(getString(R.string.data_ssid)),
intent.getStringExtra(getString(R.string.data_capabilities)),
intent.getIntExtra(getString(R.string.data_level), 0),
intent.getIntExtra(getString(R.string.data_frequency), 0),
intent.getStringExtra(getString(R.string.data_timestamp)),
intent.getDoubleExtra(getString(R.string.data_latitude), 0),
intent.getDoubleExtra(getString(R.string.data_longitude), 0)));
}
}
Unten ist der doInBackground Code für die AsyncTask
@Override
protected Integer doInBackground(ArrayList<ResponseObject>... params) {
ArrayList<ResponseObject> entries = params[0];
try {
URL url = new URL(insertURL);
for (Iterator<ResponseObject> it = entries.iterator(); it.hasNext();) {
ResponseObject ro = it.next(); // THIS IS WHERE THE EXCEPTION REFERENCES IN THE DEBUG OUTPUT
HttpURLConnection urlConnection = (HttpURLConnection)url.openConnection();
urlConnection.setRequestMethod("POST");
urlConnection.setRequestProperty("USER-AGENT", "Mozilla/5.0");
urlConnection.setRequestProperty("ACCEPT-LANGUAGE", "en-US,en;0.5");
urlConnection.setDoOutput(true);
String postParams = "bssid=" + ro.BSSID
+ "&ssid=" + ro.SSID
+ "&capabilities=" + ro.CAPABILITIES
+ "&level=" + String.valueOf(ro.LEVEL)
+ "&frequency=" + String.valueOf(ro.FREQUENCY)
+ "×tamp=" + ro.TIMESTAMP
+ "&lat=" + String.valueOf(ro.LAT)
+ "&long=" + String.valueOf(ro.LON);
DataOutputStream wr = new DataOutputStream(urlConnection.getOutputStream());
wr.writeBytes(postParams);
wr.flush();
wr.close();
Log.d("RemoteDatabase : ", "Post sent " + ro.BSSID + " || " + String.valueOf(urlConnection.getResponseCode()));
}
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (ProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
entries.clear();
return null;
}
EDIT - Ich erscheinen das Problem zurückgeführt haben abwärts zu einem anderen Abschnitt des Codes, in denen eine Sendung auf Klick auf den Button gesendet wird . Die Taste sendet definitiv nur einmal (wurde mit Log.d geprüft), aber die empfangene in der Datenbank empfängt sie zweimal. Versuche das jetzt zu beheben.
Wissen Sie, was eine 'ConcurrentModificationException' ist? Weißt du, warum es ein Problem sein könnte, ein Element zu einer Liste in einem Thread hinzuzufügen, während du es in einem anderen Thread wiederholst? –
@AndyTurner Ich weiß, was dieser Fehler ist, aber ich sollte es nicht in einem Thread und Iterieren in einem anderen ändern - die Iteration sollte erst beginnen, wenn der Databaser "Done" an den Haupt-Thread sendet, was bedeutet, dass die Liste abgeschlossen ist. – Brae