安卓探究ListView+Adapter数据在工作线程中更新引发的crash以及解决方法(三)

本文探讨了Android ListView在工作线程中更新数据导致的Crash问题,建议在UI线程进行数据更新以避免卡顿。提出一种解决方案,即捕获异常并在UI线程中执行notifyDataSetChanged()。通过源码分析和测试Demo验证,该方案可以有效防止Crash并保持UI正确绘制。
摘要由CSDN通过智能技术生成

第三部分 solution及测试

 

从上面的分析可以看出安卓希望的ListView+Adapter使用方式是更新数据,然后调用notifyDataSetChanged()触发重绘,整个过程在UI线程串行执行,框架逻辑会保证健壮可用。所以exception的描述也是说Make sure the content of your adapter is not modified from a background thread, but only from the UI thread。所以在UI线程更新数据显然是一种solution。但这就失去了工作线程的并行优势,容易引起UI卡顿。所以需要一种保持工作线程执行数据更新的解决此crash的方案。

 

这里设想一种方案:catch这个exception,并postUI线程执行notifyDataSetChanged(),触发重绘。

 

这个方案的疑问在于,catch这个exception,不让应用进程挂掉,继续活下去,是否足够健壮能够恢复正确的UI绘制?下面从框架源代码分析和app demo测试两个角度验证一下这个方案。

 

先源码分析。前文分析可知触发重绘的关键在于requestLayout()。这里先简单看看requestLayout()。这个方法源自View,先看看View中对于这个方法的注释:

    /**
     * Call this when something has changed which has invalidated the
     * layout of this view. This will schedule a layout pass of the view
     * tree. This should not be called while the view hierarchy is currently in a layout
     * pass ({@link #isInLayout()}. If layout is happening, the request may be honored at the
     * end of the current layout pass (and then layout will run again) or after the current
     * frame is drawn and the next layout occurs.
     *
     * <p>Subclasses which override this method should call the superclass method to
     * handle possible request-during-layout errors correctly.</p>
     */
    @CallSuper
public void requestLayout() {
......
}

注释中并没有说得很确定,且ListView距离View已经有多层的继承关系,requestLayout()可能被重写。从ViewListView的继承链为View->ViewGroup->AdapterView->AbsListView->ListView,对于requestLayout()方法检查结果如下:

ViewGroup.requestLayout() 未重写,等价于 V

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值