Java 刷新时listView随机崩溃
我有一个listView,每次客户端(我的android应用程序)从服务器收到消息时都会刷新,但问题是当我多次单击刷新按钮时,应用程序崩溃并向我发送此错误:Java 刷新时listView随机崩溃,java,android,listview,Java,Android,Listview,我有一个listView,每次客户端(我的android应用程序)从服务器收到消息时都会刷新,但问题是当我多次单击刷新按钮时,应用程序崩溃并向我发送此错误:java.lang.IllegalStateException:适配器的内容已更改,但listView未收到通知。确保适配器的内容不是从后台线程修改的,而是仅从UI线程修改的。确保适配器在其内容更改时调用notifyDataSetChanged()。 编辑1:崩溃不会每次都发生,只要我快速点击刷新按钮十次 活动代码: class recei
java.lang.IllegalStateException:适配器的内容已更改,但listView未收到通知。确保适配器的内容不是从后台线程修改的,而是仅从UI线程修改的。确保适配器在其内容更改时调用notifyDataSetChanged()。
编辑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);
}
});
}
class receiveimplements可运行{
@凌驾
公开募捐{
试一试{
if(socket!=null&&socket.isConnected()){
BufferedReader=新的BufferedReader(新的InputStreamReader(socket.getInputStream());
对于(;;){
而((textrec=reader.readLine())!=null){
if(textrec.length()<6){
bug=true;
打破
}
Log.d(“textrecapres”,textrecure);
索引++;
如果(索引==1){
添加(0,textRecu);
SendListendMakeAffichage(列表源、列表标题);
}else if(索引==2){
添加(0,textrec);
指数=0;
}
}
}
}
}捕获(未知后异常e){
e、 printStackTrace();
}捕获(IOE异常){
e、 printStackTrace();
}捕捉(中断异常e){
e、 printStackTrace();
}
}
}
public void sendliste和makeAffichage(最终列表源列表,最终列表源标题){
runOnUiThread(新的Runnable(){
@凌驾
公开募捐{
FragmentList.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 setListTitreAndListSource(List listTitre,List listSource){
this.listTitre=listTitre;
this.listSource=listSource;
适配器绑定(列表标题);
setListAdapter(适配器);
}
适配器代码:
public void bind(List<String> model) {
notifyDataSetChanged();
listeTitre = model;
notifyDataSetChanged();
}
公共无效绑定(列表模型){
notifyDataSetChanged();
李斯特=模型;
notifyDataSetChanged();
}
正如错误消息通知您的那样,您不能从非UI线程修改UI元素(并且您的可运行
使用单独的线程)
使用
处理程序
更新UI线程。查看此答案,例如:当您添加到列表标题时,不调用notifyDataSetChanged()
这将更改适配器的内容。您确实安排了对notifyDataSetChanged()
的调用,但是不能保证在ListView的呈现(将验证其状态)之前安排调用。适配器必须在与notifyDataSetChanged()
调用相同的已处理消息中进行操作,以确保在下一次渲染中同时发生
所以现在你正在做:
线程-1:
添加到列表中
主线程:
evaluatePendingMessages([validate ListView,runnable,调用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);
}
});
}
public void sendliste和makeAffichage(最终列表sourceList、最终列表sourceTitre、最终字符串newEntry){
runOnUiThread(新的Runnable(){
@凌驾
公开募捐{
add(newEntry);//现在我们在这个runnable
//而对片段的下一次调用将完成对适配器的更新
//并调用notifyDataSetChanged()
FragmentList.setListTitreAndListSource(sourceTitre,sourceList);
}
});
}
我遇到了与以前相同的错误,我忘了说崩溃不是每次都会发生,它只是在我快速单击刷新按钮大约十次时才会发生,所以您建议我添加notifyDataSetChanged();此处?public void sendliste和makeAffichage(最终列表源列表,最终列表源标题){rununuithread(new Runnable(){@Override public void run(){fragmentListe.setListTitreAndListSource(sourceTitre,sourceList);}});
No您已经在fragment.Liste.setListTier..中执行了此操作。);
我是说你必须在同一个Runnable中执行添加和notifyDataSetChanged。你的textRecu应该添加到UIThread上的同一个Runnable中。非常感谢你的帮助:)它可以工作,我不知道我曾经在UI线程中操纵列表
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);
}
});
}