[英]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.