Android app主线程UI更新间歇性崩溃的问题

简介:

 对App进行开发测试时,偶尔出现app崩溃的问题。日志如下:

复制代码
10-25 18:44:52.935  15290-15290/com.zzq.cnblogs E/AndroidRuntime﹕ FATAL EXCEPTION: main
    Process: com.zzq.cnblogs, PID: 15290
    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. [in ListView(16908298, class com.handmark.pulltorefresh.library.PullToRefreshListView$InternalListViewSDK9) with Adapter(class android.widget.HeaderViewListAdapter)]
            at android.widget.ListView.layoutChildren(ListView.java:1555)
            at android.widget.AbsListView.onLayout(AbsListView.java:2089)
            at android.view.View.layout(View.java:14845)
            at android.view.ViewGroup.layout(ViewGroup.java:4631)
            at android.widget.FrameLayout.layoutChildren(FrameLayout.java:453)
            at android.widget.FrameLayout.onLayout(FrameLayout.java:388)
            at android.view.View.layout(View.java:14845)
            at android.view.ViewGroup.layout(ViewGroup.java:4631)
            at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1671)
            at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1525)
            at android.widget.LinearLayout.onLayout(LinearLayout.java:1434)
            at android.view.View.layout(View.java:14845)
            at android.view.ViewGroup.layout(ViewGroup.java:4631)
            at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1671)
            at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1525)
            at android.widget.LinearLayout.onLayout(LinearLayout.java:1434)
            at android.view.View.layout(View.java:14845)
            at android.view.ViewGroup.layout(ViewGroup.java:4631)
            at android.widget.RelativeLayout.onLayout(RelativeLayout.java:1055)
            at android.view.View.layout(View.java:14845)
            at android.view.ViewGroup.layout(ViewGroup.java:4631)
            at android.widget.FrameLayout.layoutChildren(FrameLayout.java:453)
            at android.widget.FrameLayout.onLayout(FrameLayout.java:388)
            at android.view.View.layout(View.java:14845)
            at android.view.ViewGroup.layout(ViewGroup.java:4631)
            at android.support.v4.widget.DrawerLayout.onLayout(DrawerLayout.java:1043)
            at android.view.View.layout(View.java:14845)
            at android.view.ViewGroup.layout(ViewGroup.java:4631)
            at android.widget.FrameLayout.layoutChildren(FrameLayout.java:453)
            at android.widget.FrameLayout.onLayout(FrameLayout.java:388)
            at android.view.View.layout(View.java:14845)
            at android.view.ViewGroup.layout(ViewGroup.java:4631)
            at android.support.v7.internal.widget.ActionBarOverlayLayout.onLayout(ActionBarOverlayLayout.java:437)
            at android.view.View.layout(View.java:14845)
            at android.view.ViewGroup.layout(ViewGroup.java:4631)
            at android.widget.FrameLayout.layoutChildren(FrameLayout.java:453)
            at android.widget.FrameLayout.onLayout(FrameLayout.java:388)
            at android.view.View.layout(View.java:14845)
            at android.view.ViewGroup.layout(ViewGroup.java:4631)
            at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1671)
            at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1525)
            at android.widget.LinearLayout.onLayout(LinearLayout.java:1434)
            at android.view.View.layout(View.java:14845)
            at android.view.ViewGroup.layout(ViewGroup.java:4631)
            at android.widget.FrameLayout.layoutChildren(FrameLayout.java:453)
            at android.widget.FrameLayout.onLayout(FrameLayout.java:388)
            at android.view.View.layout(View.java:14845)
            at android.view.ViewGroup.layout(ViewGroup.java:4631)
            at android.view.ViewRootImpl.performLayout(ViewRootImpl.java:2026)
            at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1783)
            at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1039)
            at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:5648)
            at android.view.Choreographer$CallbackRecord.run(Choreographer.java:761)
            at android.view.Choreographer.doCallbacks(Choreographer.java:574)
            at android.view.Choreographer.doFrame(Choreographer.java:544)
            at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:747)
            at android.os.Handler.handleCallback(Handler.java:733)
            at android.os.Handler.dispatchMessage(Handler.j
复制代码

  其中

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.

  由异常的提示可以看出,在一个后台线程更新了UI界面,而UI界面必须由UI线程进行更新。然而,Android提供了几种更新UI线程的方法。下面用Handler的方式更新UI,做个简单的修改即可。更多关于UI线程更新的方法见:http://gqdy365.iteye.com/blog/2112471

  1、添加一个Handler属性

复制代码
    private Handler handlerListView = new Handler(){
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            Bundle bundle = (Bundle) msg.obj;
            int refreshType = (int) bundle.get("refreshType");
            LinkedList<Article> list = (LinkedList<Article>) bundle.get("article");
            for (Article article : list){
                if (REFRESH_TYPE_UP == refreshType){
                    listData.add(article);
                }else if (REFRESH_TYPE_DOWN == refreshType){
                    listData.add(0, article);
                }
            }

            pullToRefreshView.onRefreshComplete();
            adapter.notifyDataSetChanged();
        }
    };
复制代码

  2、将直接更新UI内容的部分

  pullToRefreshView.onRefreshComplete();
  adapter.notifyDataSetChanged();

  改成

    Message msg = new Message();
    Bundle bundle = new Bundle();
    bundle.putInt("refreshType", refreshType);
    bundle.putSerializable("article", addList);
    msg.obj = bundle;
    handlerListView.sendMessage(msg);

  将修改的数据发给handler去处理,而不是直接操作listview的adapter。

  此外还可以考虑使用activity的runOnUiThread方法进行更新。






本文转自秋楓博客园博客,原文链接:http://www.cnblogs.com/rwxwsblog/p/4910575.html,如需转载请自行联系原作者
目录
相关文章
|
21天前
|
存储 Java API
Android 浅度解析:mk预置AAR、SO文件、APP包和签名
Android 浅度解析:mk预置AAR、SO文件、APP包和签名
77 0
|
3天前
|
移动开发 jenkins 持续交付
jenkins编译H5做的android端编译卫士app记录
jenkins编译H5做的android端编译卫士app记录
|
6天前
|
Android开发
Android APP 隐藏系统软键盘的方法
Android APP 隐藏系统软键盘的方法
11 0
|
6天前
|
Android开发
Android修改默认system/bin/下可执行程序拥有者和权限,使用实例,只有root和系统app权限才能执行某个命令。
Android修改默认system/bin/下可执行程序拥有者和权限,使用实例,只有root和系统app权限才能执行某个命令。
12 0
|
20天前
|
XML Java Android开发
Android系统 添加动态控制屏幕方向、强制APP横竖屏方向
Android系统 添加动态控制屏幕方向、强制APP横竖屏方向
35 1
|
21天前
|
测试技术 Android开发
Android App获取不到pkgInfo信息问题原因
Android App获取不到pkgInfo信息问题原因
19 0
|
26天前
|
Android开发 UED 开发者
解释Android App Bundle是什么,它的优势是什么?
Android App Bundle是Google开发的优化应用分发技术,它打包应用及资源以减少下载大小,加快加载速度,节省用户流量。App Bundle支持离线使用,简化更新过程,提升用户体验。开发人员借此能更高效地构建和分发Android应用。
13 0
|
2月前
|
前端开发 搜索推荐 开发者
SAP UI5 sap.m.Column 控件的 minScreenWidth 属性介绍
SAP UI5 sap.m.Column 控件的 minScreenWidth 属性介绍
32 0
|
2月前
|
JavaScript 前端开发 开发者
SAP UI5 控件 sap.m.ListBase 的 inset 属性的作用介绍
SAP UI5 控件 sap.m.ListBase 的 inset 属性的作用介绍
17 0
|
2月前
|
前端开发 JavaScript API
SAP UI5 sap.ui.require.toUrl 的作用介绍
SAP UI5 sap.ui.require.toUrl 的作用介绍
35 0