listView在刷新时随机崩溃

时间:2014-01-01 22:28:34

标签: java android listview

我有一个listView whixh每次客户端(我的Android应用程序)从服务器收到消息时刷新,但问题是当我点击刷新按钮时很多时间应用程序崩溃并向我发送此错误:{{ 1}}

编辑1:当我在刷新按钮上快速点击十次时发生崩溃时不会发生崩溃

活动代码:

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.

Listfragment代码:

 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);

        }
    });

}

适配器代码:

public void setListTitreAndListSource(List<String> listTitre, List<String> listSource) {

    this.listTitre = listTitre;
    this.listSource = listSource;

    adapter.bind(listTitre);
    setListAdapter(adapter);
}

2 个答案:

答案 0 :(得分:4)

当您添加到listTitre时,不会调用notifyDataSetChanged()

  if (index == 1) {
     listTitre.add(0, textRecu);
     sendListeAndMakeAffichage(listSource,listTitre);

这正在改变适配器的内容。您确实安排了对notifyDataSetChanged()的调用,但是不能保证在ListView的渲染之前调度它将验证它的状态。必须在与notifyDataSetChanged()调用相同的处理消息中操作适配器,以确保在下一次渲染中一次性完成所有操作。

现在你正在做:

主题-1:   添加到列表

主线程:   evaluatePendingMessages([验证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);

        }
    });

}

答案 1 :(得分:3)

当错误消息通知您时,您无法从非UI线程修改UI元素(并且您的Runnable使用单独的线程)。

使用Handler更新UI线程。请参阅此答案,例如:https://stackoverflow.com/a/12717105/240646