[英]listView crashed randomly when refresh
每當客戶端(我的android應用)從服務器收到消息時,我都有一個listView刷新,但是問題是,當我在刷新按鈕上單擊很多次時,應用崩潰,並向我發送此錯誤: java.lang.IllegalStateException: The content of the adapter has changed but ListView did not receive a notification. Make sure the content of your adapter is not modified from a background thread, but only from the UI thread. Make sure your adapter calls notifyDataSetChanged() when its content changes.
java.lang.IllegalStateException: The content of the adapter has changed but ListView did not receive a notification. Make sure the content of your adapter is not modified from a background thread, but only from the UI thread. Make sure your adapter calls notifyDataSetChanged() when its content changes.
編輯1:當我在刷新按鈕上快速單擊大約十次時,崩潰不會在每次發生時發生
活動代碼:
class receiveimplements Runnable {
@Override
public void run() {
try {
if (socket != null && socket.isConnected()) {
BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
for (; ; ) {
while ((textRecu = reader.readLine()) != null) {
if (textRecu.length() < 6) {
bug = true;
break;
}
Log.d("textrecuapres", textRecu);
index++;
if (index == 1) {
listTitre.add(0, textRecu);
sendListeAndMakeAffichage(listSource,listTitre);
} else if (index == 2) {
listSource.add(0, textRecu);
index = 0;
}
}
}
}
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public void sendListeAndMakeAffichage(final List<String> sourceList,final List<String> sourceTitre) {
runOnUiThread(new Runnable() {
@Override
public void run() {
fragmentListe.setListTitreAndListSource(sourceTitre, sourceList);
}
});
}
Listfragment代碼:
public void setListTitreAndListSource(List<String> listTitre, List<String> listSource) {
this.listTitre = listTitre;
this.listSource = listSource;
adapter.bind(listTitre);
setListAdapter(adapter);
}
適配器代碼:
public void bind(List<String> model) {
notifyDataSetChanged();
listeTitre = model;
notifyDataSetChanged();
}
當您添加到listTitre
,無需調用notifyDataSetChanged()
if (index == 1) {
listTitre.add(0, textRecu);
sendListeAndMakeAffichage(listSource,listTitre);
這正在更改適配器的內容。 您確實安排了對notifyDataSetChanged()
的調用,但是並不能保證將其安排在ListView的呈現器之前進行,以驗證其狀態。 必須確保在與notifyDataSetChanged()
調用相同的已處理消息中處理適配器,以確保適配器在下一次呈現時立即發生。
所以現在您正在做:
線程-1:添加到列表
主線程: notifyDataSetChanged()
[驗證ListView,運行notifyDataSetChanged()
runnable]
您必須在與更新適配器的部分相同的事件中修改適配器(而且它們都必須從主線程中啟動)
因此,如果這在您的邏輯上有效,則應執行此操作。
if (index == 1) {
sendListeAndMakeAffichage(listSource,listTitre, textRecu);
} ....
然后在該方法內部:
public void sendListeAndMakeAffichage(final List<String> sourceList,final List<String> sourceTitre, final String newEntry) {
runOnUiThread(new Runnable() {
@Override
public void run() {
listTitre.add(newEntry); // Now we manipulate the list in this runnable
// While the next call to the fragment will finish updating the adapter
// and call notifyDataSetChanged()
fragmentListe.setListTitreAndListSource(sourceTitre, sourceList);
}
});
}
如錯誤消息所通知,您不能從非UI線程修改UI元素(您的Runnable
使用單獨的線程)。
使用Handler
程序更新UI線程。 參見以下答案,例如: https : //stackoverflow.com/a/12717105/240646
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.