2012-05-20 96 views
3

我認爲這不是一個簡單的問題。 我會簡要介紹一下正在發生的事情。 比方說,我們有數據的源文件Byron.txt:Android AsyncTask奇怪地發佈重複

她走在美,像黑夜
皎潔無雲而且繁星滿天;
和所有的「她的樣子和她的眼睛最好的黑暗和明亮
相約:
因此越加醇美那溫柔的光
就是天堂會餐日對此予以否認。

而這種代碼執行的AsyncTask裏面:

final ArrayList<Record> poem = new ArrayList<Record>(); 
final Object objectLock = new Object(); 
private Record rec = new Record(); 

@Override 
protected Void doInBackground(Void... args) { 
    String line = null; 
    int i; 
    int last; 

    try { 
     process = Runtime.getRuntime().exec("cat Byron.txt"); 
     bufferedReader = new BufferedReader(new InputStreamReader(process.getInputStream()), 8192); 

     synchronized (objectLock) { 
      poem.clear(); 
      last = i = poem.size() - 1; 
     } 
     while(line = bufferedReader.readLine()) != null) { 
      rec.setString(line); 
      synchronized (objectLock) { 
       last++; 
       poem.add(last, rec); 
      } 

      while(!bPause && i < last) { 
       i++; 
       publishProgress(poem.get(i)); 
      } 
     } 
    } 
    catch (Exception e) { 
     e.printStackTrace(); 
    } 
    return null; 
} 

@Override 
protected synchronized void onProgressUpdate(Record... m) { 
    if(m.length > 0) { 
     mContext.mTable.appendRow(m[0]); 
    } 

} 

那裏是在UI每次TableLayout,我們得到一個新的生產線,我們添加一個新的TableRow它。 這是我們在UI看到輸出:

她走在美,像黑夜
皎潔無雲而且繁星滿天;
無雲的天空和滿天星斗的天空;
無雲的天空和滿天星斗的天空;
因此越加醇美那溫柔的光
因此越加醇美那溫柔的光

我們進入調試器,我們可以看到爲什麼它會發生。
有時跳過synchronized (objectLock)並繼續循環。
沒有發佈,因爲i已經捕獲last
後來塊被執行多次,因爲它是跳過,
,但原來的線丟失,當前行,而不是添加到poem幾次
然後,所有新線發佈,直到i漁獲last再次。

所以你看我跟着代碼,我可以解釋發生了什麼,這裏的問題是:爲什麼塊被跳過?,爲什麼?
我期待同步塊停頓,直到它可以執行。
至少,這怎麼理解synchronized (objectLock)
功能即使不使用wait()notify()

我不假裝在這裏開設的討論(雖然如果你想要,我們可以打開一個聊天區)
如果您在代碼中看到錯誤,請回答問題以讓我知道。

注:

  1. ​​需要,因爲其他地方的應用程序,用戶可能希望通過電子郵件他得到了迄今爲​​止線。
  2. 用戶可以暫停出版(bpause);這就是while環和i如下last只有當bPause是假的。

回答

3

我決定公佈答案。即使我覺得尷尬由其簡單。
我發現它只有在我已經挖深入到AsyncTask類和消息處理和諸如此類的東西。

我發佈它在希望這將有助於人們過早下結論 前檢查基本的東西,那有人能救自己,因爲 這個帖子,每天調試一半。

Record rec每次都是一樣的。 poem ArrayList具有每個條目相同的元素ID。所有這些內容都立即改變了,因爲它們都是一樣的。
當進度立即發佈時,它會打印最後一個正確的字符串。但是如果延遲導致進度稍後公佈,那麼檢索poem.get(i)記錄檢索到不同的條目,但具有相同的指針,因此具有相同的內容。

的解決方案是創建一個新的記錄每個循環。

+0

感謝您將答案。如果他們自己找到答案,大多數人並不在乎添加答案。沒有什麼好尷尬的,這種事情偶爾會發生在所有程序員身上。 – Ronnie

0

last對象的同步。

synchronized (last) { 
    last++; 
    poem.add(last, line); 
} 
+0

到目前爲止,它不作任何區別,我會繼續調試 – ilomambo

+0

嘗試同步最後一個對象上..做最後一個整數,如果necesary – Ronnie