Yeterince açıklayabileceğimi umduğum garip bir konu var. Uygulamamın iki etkinliği var: MainActivity ve SearchActivity. MainActivity üzerinde, cihazdaki veritabanından web sunucumdaki uzak bir veritabanına bir yükleme tetikleyen bir düğmem var. Uygulamayı ilk başlattığımda düğmeyi tıklarsam sorun olmaz, iyi çalışıyor. SearchActivity'ye geçersem, hiçbir şey yapmaz ve geri dönersek düğmeyi deneyin, uygulama ConcurrentModificationException ile çöker. Yerel bir veritabanının içeriğini (zaten veritabanından çıkardı ve bir ArrayList olarak parametreler aracılığıyla iş parçacığına gönderilen) gönderen bir AsyncTask var. Bunu hata ayıklamak için saatler harcadım ve hala nerede olduğunu anlayamıyorum. Herhangi bir öneri çok takdir edilecektir.Android'de ConcurrentModificationException AsyncTask
Bu kod Bu databaser her yanıtını alır ve bunları toplar BroadcastReceiver içinde kodudur
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);
}
});
ayrı Databaser iplikten veritabanının içeriğini istemek için, düğmesine basın üzerinde tetiklenen olduğunu özel ResponseObjects bir ArrayList. Veritabanının iş parçacığı bir BOSID değeri gönderdiğinde, AsyncTask ArrayList parametresi olarak geçirilerek başlatılır. Aşağıda
@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)));
}
}
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;
}
DÜZENLEME için doInBackground kodudur - Bir yayın tuşuna gönderilir başka bir kod bölümüne, aşağı sorunu takip görünmektedir . Düğme kesinlikle sadece bir kez gönderir (Log.d kullanarak kontrol edildi) ancak veritabanında alınan iki kez alır. Bunu düzeltmeye çalışıyorum.
ConcurrentModificationException öğesinin ne olduğunu biliyor musunuz? Başka bir iş parçacığında yinelemek için neden bir iş parçacığı listeye bir öğe eklemek sorun olabilir biliyor musunuz? –
@AndyTurner Bu hatanın ne olduğunu biliyorum, ancak bunu bir iş parçacığında değiştirmemeli ve bir diğerinde yinelememeliyiz - yineleme, Veritabanının yalnızca listenin tamamlandığı ana iş parçacığına "Bitti" gönderdiğinde başlamalıdır. – Brae