Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/335.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java Android AsyncTask中的ConcurrentModificationException_Java_Android_Arraylist_Android Asynctask_Concurrentmodification - Fatal编程技术网

Java Android AsyncTask中的ConcurrentModificationException

Java Android AsyncTask中的ConcurrentModificationException,java,android,arraylist,android-asynctask,concurrentmodification,Java,Android,Arraylist,Android Asynctask,Concurrentmodification,我有一个奇怪的问题,我希望我能解释清楚。我的应用程序有两个活动-MainActivity和SearchActivity。我在MainActivity上有一个按钮,可以触发从设备上的数据库上传到web服务器上的远程数据库。如果我在第一次启动应用程序时单击该按钮,没问题,工作正常。如果我切换到SearchActivity,不做任何事情,然后切换回,然后尝试该按钮,应用程序将崩溃,出现ConcurrentModificationException。 我有一个AsyncTask,它发送本地数据库的内容(

我有一个奇怪的问题,我希望我能解释清楚。我的应用程序有两个活动-MainActivity和SearchActivity。我在MainActivity上有一个按钮,可以触发从设备上的数据库上传到web服务器上的远程数据库。如果我在第一次启动应用程序时单击该按钮,没问题,工作正常。如果我切换到SearchActivity,不做任何事情,然后切换回,然后尝试该按钮,应用程序将崩溃,出现ConcurrentModificationException。 我有一个AsyncTask,它发送本地数据库的内容(已经从数据库中取出并作为ArrayList通过参数发送到线程)。我花了几个小时调试这个,但仍然无法确定它在哪里。如有任何建议,将不胜感激

这是按下按钮时触发的代码,用于从单独的数据库线程请求数据库内容

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);
        }
    });
这是BroadcastReceiver中的代码,它从数据库获取每个响应,并将它们添加到自定义响应对象的ArrayList中。当databaser线程发送一个bssid值DONE时,AsyncTask将启动,并将ArrayList作为参数传入

@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)));

       }
    }
下面是异步任务的doInBackground代码

@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)
                    + "&timestamp=" + 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;
}
@覆盖
受保护的整数doInBackground(ArrayList…params){
ArrayList条目=参数[0];
试一试{
URL=新URL(插入URL);
for(Iterator it=entries.Iterator();it.hasNext();){
ResponseObject ro=it.next();//这是异常在调试输出中引用的位置
HttpURLConnection urlConnection=(HttpURLConnection)url.openConnection();
urlConnection.setRequestMethod(“POST”);
setRequestProperty(“用户代理”、“Mozilla/5.0”);
setRequestProperty(“ACCEPT-LANGUAGE”,“en-US,en;0.5”);
urlConnection.setDoOutput(true);
字符串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=新的DataOutputStream(urlConnection.getOutputStream());
wr.writeBytes(后参数);
wr.flush();
wr.close();
Log.d(“RemoteDatabase:”,“Post-sent”+ro.BSSID+“| |”+String.valueOf(urlConnection.getResponseCode());
}
}捕获(格式错误){
e、 printStackTrace();
}捕获(协议例外e){
e、 printStackTrace();
}捕获(IOE异常){
e、 printStackTrace();
}
条目。清除();
返回null;
}


编辑——我似乎已经把这个问题追溯到了另一段代码,在这段代码中,单击按钮就会发送广播。该按钮肯定只发送一次(使用Log.d进行了检查),但数据库中接收到的消息会接收两次。正在尝试立即修复此问题。

请在异步任务的onPreExecute()方法中插入进度条,并在onPostExecute()中取消它。我认为完成异步任务花费的时间太长,您正在异步任务完成前再次点击按钮。

请在onPreExecute()中插入进度条方法,并在onPostExecute()中取消它。我认为完成异步任务花费的时间太长,并且您在异步任务完成之前再次点击按钮。

已经有一段时间了,但意识到我忘了添加如何解决此问题,以防万一这对其他人有帮助

我发现这里的问题实际上是一些Android设备发送多个广播副本。我使用HTC手机进行测试,显然出于某种原因,他们发送了所有广播的2份副本。我的代码的工作方式是从广播中产生一个线程,这导致两个相同的线程在相同的数据上运行。当这些任务完成时,他们每个人都在发送他们的“完成”广播,这导致主线程接收到其中的4个任务。一团糟。
最后,我不得不在每次广播中添加一个唯一的ID标记,并在接收端记录值,因此,如果同一ID被接收两次,第二次就不会采取任何行动。

有一段时间了,但我意识到我忘了添加我是如何解决这个问题的,以防万一这对其他人有帮助

我发现这里的问题实际上是一些Android设备发送多个广播副本。我使用HTC手机进行测试,显然出于某种原因,他们发送了所有广播的2份副本。我的代码的工作方式是从广播中产生一个线程,这导致两个相同的线程在相同的数据上运行。当这些任务完成时,他们每个人都在发送他们的“完成”广播,这导致主线程接收到其中的4个任务。一团糟。
最后,我不得不为每个广播添加一个唯一的ID标记,并在接收端记录值,因此,如果两次接收到相同的ID,则第二次不会采取任何行动。

您知道什么是
ConcurrentModificationException
?你知道为什么在一个线程中添加一个元素,而在另一个线程中迭代时,在一个线程中添加一个元素可能会出现问题吗?@AndyTurner我知道错误是什么,但我不应该在一个线程中修改它,然后在另一个线程中迭代-只有在数据库向主线程发送“完成”后,迭代才会开始,意思是列表已完成。您知道什么是
ConcurrentModificationException
?你知道为什么在一个线程中向列表中添加一个元素,而在另一个线程中对其进行迭代时会出现问题吗?@AndyTurner我知道这个错误是什么