2013-12-17 64 views
0

我使用的是聽一個服務器,並作出了publishProgess(receivedMessage)每次收到郵件時的的AsyncTask,所以我保存具體信息在一個字段「ArrayList messageStrings;」中。使用信息去「OnProgressUpdate」中的AsyncTask(安卓)的

現在我想訪問「messageStrings」從的AsyncTask類以外-Arraylist,但當然,我得到一個「ConcurrentModificationException的」誤差。

我曾經試圖「同步」使用它的所有功能,但我不會幫助。

那麼如何處理出的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

你可以分享你的代碼的一部分線程...? –

+0

對不起,我希望這可以幫助。 – Reyny

+0

你可以宣佈你的ArrayList揮發性,當你修改列表中使用synchronized塊......只有當你正在使用列表... –

回答

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,因爲所有事情都是從一開始就改變了。如果他們是非易失性

+0

喲,你是對的! ......非常好的眼睛! – Reyny

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(); 
      } 
     } 
    } 

線程可以創建變量的本地副本內。揮發性指出不創建本地副本內

+1

線程可能會緩存由變量引用的對象,而不是每次在代碼中使用變量時都讀取它。 'volatile'確保其他線程可以看到對該變量所做的更改(它們每次都必須刷新該值)。例如。在這個例子中,如果一個線程將一個完全不同的'ArrayList'分配給'stringList'。但是沒有任何東西改變'stringList'引用的對象,所以'volatile'只會導致同步開銷。對ArrayList的內容所做的更改也不會繼承引用其「容器」的變量的volatile屬性。 – zapl

+0

@zapl感謝您分享您的知識...... –