我有一个 listView,每次客户端(我的 Android 应用程序)从服务器收到消息时都会刷新,但问题是当我多次单击刷新按钮时,应用程序崩溃并向我发送此错误:java.lang.IllegalStateException:适配器的内容已更改,但 ListView 未收到通知。确保适配器的内容不是从后台线程修改的,而是仅从 UI 线程修改的。确保您的适配器在其内容更改时调用notifyDataSetChanged()。
编辑1:崩溃不会每次都发生,只有当我快速单击刷新按钮大约十次时才会发生
Activity 代码:
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);
}
});
}
列表 fragment 代码:
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: 添加到列表
主线程:
评估PendingMessages([验证ListView,可运行,调用notifyDataSetChanged()
]
您必须在与更新适配器的部分相同的事件中修改适配器(并且它们都必须来自主线程)
因此,如果这符合您的逻辑,您应该这样做。
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);
}
});
}
关于java - listView 刷新时随机崩溃,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20873953/