我正在使用正在侦听服务器的AsyncTask,并在每次收到消息时生成publishProgess(receivedMessage),因此我将特定消息保存在“ArrayList messageStrings;”字段中。
现在我想从AsyncTask类的Outside访问“messageStrings”-Arraylist,但当然我得到一个“concurrentmodificationexception”-Error。
我试图“同步”所有使用它的功能,但我不会帮忙。
那么如何正确处理AsyncTask中的消息呢?
代码:
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.Socket;
import java.util.ArrayList;
import android.os.AsyncTask;
public class ReadInStream extends AsyncTask<Object, String, Object> {
Socket socket;
public ArrayList<String> stringList;
//Socket der Verbindung
public ReadInStream(Socket socket) {
this.socket = socket;
this.stringList = new ArrayList<String>();
}
@Override
protected Object doInBackground(Object... arg0) {
try {
System.out.println("Thread ReadInStream started.");
BufferedReader inStream = new BufferedReader(
new InputStreamReader(socket.getInputStream()));
while (true) {
// jede Zeile einlesen und überprüfen, ob sie etwas enthaelt
String inputLine = inStream.readLine();
if (inputLine != null && inputLine.trim() != ""
&& inputLine.length() > 0) {
System.out.println("Recieved: " + inputLine);
publishProgress(inputLine);
}
}
} catch (Exception e) {
e.printStackTrace();
}
return "";
}
@Override
protected synchronized void onProgressUpdate(String... values) {
super.onProgressUpdate(values);
stringList.add(values[0]);
}
public synchronized ArrayList<String> getStringList(){
return this.stringList;
}
}
我称之为:
commandList = serverConnection.readIn.getStringList();
for(String item: commandList){
if (item.startsWith("71 53 11 40")){
CofKleinEsp = Integer.decode(item.substring(12));
System.out.println(CofKleinEsp);
commandList.remove(item);}
答案 0 :(得分:2)
您的ConcurrentModificationException
与AsyncTask
无关。在Ui线程中调用onProgressUpdate
并且它不与doInBackground
共享任何可变状态。除非ui线程触及stringList
,否则不需要同步。
你的问题是
for (String item : commandList) {
commandList.remove(item);
}
您在迭代时修改列表。这也是一个并发修改。要解决此问题,请使用Iterator
删除项目。这样,迭代器(也在上面隐式使用)将知道何时删除元素并且不再抱怨。
for (Iterator<String> iterator = commandList.iterator(); iterator.hasNext();) {
String item = iterator.next();
iterator.remove();
}
您拥有的第二个选项是使用索引循环并从后面遍历列表。
for (int i = commandList.size() - 1; i > 0; i--) {
commandList.remove(i);
}
你也可以从头到尾完成它,但是你必须处理变化的索引。删除i
后,您的下一次迭代必须再次处理i
,因为所有内容都已向前移动了一次。
答案 1 :(得分:0)
试试这个......
public volatile ArrayList<String> stringList;
和
commandList = serverConnection.readIn.getStringList();
synchronized (commandList) {
Iterator<String> iterator = commandList.iterator();
while (iterator.hasNext()) {
String string = (String) iterator.next();
if(string.startsWith("71 53 11 40")) {
CofKleinEsp = Integer.decode(item.substring(12));
System.out.println(CofKleinEsp);
iterator.remove();
}
}
}
如果变量非易失性,则线程可以创建变量的本地内部副本。 volatile表示不创建本地内部副本的线程...