2.6 合理的刷新机制
在应用开发的过程中,因为数据的变化,需要刷新页面来展示新的数据,但频繁刷新会增加资源开销,并且可能导致卡顿发生,所以,需要一个合理的刷新机制来提高整体的UI流畅度。合理的刷新需要注意以下几点:
尽量减少刷新次数。
尽量避免后台有高CPU线程运行。
缩小刷新区域。
2.6.1 减少刷新次数
毫无疑问,减少刷新次数可以减少系统的开销,在功耗和页面的性能上可以表现得更优秀,但不刷新就不能及时让用户看到最新的数据,可以从以下几个方面减少刷新次数:
1.?控制刷新频率
在有些功能上需要频繁刷新某个控件(View),比如下载进度条或者播放进度条,没有必要在数据每次变化时都更新对应的控件,需要注意的是一定不能出现过度刷新(进度刷新频率大于系统显示的刷新频率)的情况。可以通过定时控制刷新频率,相同的刷新只做一次,比如播放进度条的刻度是100,如果数据变化没有1%,完全没有必要刷新,这样可以减少UI的刷新负担。
2.?避免没有必要的刷新
首先需要判断是否需要刷新,比如数据没有变化、需要刷新的控件(View)不在可见区域,就没有必要刷新。但是需要注意,如果一个View从不可见到可见,一定要刷新一次。
一般来说,在第一片数据(从无到有)和最后一片数据(结束了一个刷新周期)时,一定要刷新一次,以保证完整性。
2.6.2 避免后台线程影响
后台线程虽然不会直接影响到主线程的工作,但如果后台线程开销很大,占用CPU过高,导致系统GC频繁和CPU时间片资源紧张,还是有可能会导致页面的卡顿。因此在需要迅速刷新的情况下避免这类线程在高峰工作。比如ListView的滚动,如果ListView中的Item需要下载图片显示,在ListView滚动时可以暂停其他UI的操作,示例代码如下:
listView.setOnScrollListener(new AbsListView.OnScrollListener() {
@Override
public void onScrollStateChanged(AbsListView absListView, int scrollState) {
if (scrollState == AbsListView.OnScrollListener.SCROLL_STATE_FLING) {
mImageWorker.setPauseWork(true);
} else {
mImageWorker.setPauseWork(false);
}
}
});
通过监听ListView的onScrollStateChanged事件,在滚动时暂停图片下载线程工作,结束后再开始,可以提高ListView的滚动平滑度。
2.6.3 缩小刷新区域
在以下两个场景下可以采用局部刷新的方法来节省更多的资源。
一是在自定义View中。自定义View一般采用invalidata方法刷新。如果需要更新的数据只是在某一个区域内改变,在调用invalidata方法更新这个区域时,也会更新整个视图,这就浪费了不需要更新区域资源。Android提供系统了两个局部更新数据的方法:
invalidate(Rect dirty);
invalidate(int left, int top, int right,int bottom);
使用这两个方法可以只更新需要更新的区域,其他不需要数据更新的区域不会更新,这样能节省部分资源。
第二种是容器中的某个Item发生了变化,只需要更新这一个Item即可。比如在ListView中,如果是单条操作,就必须调用Adapter的notifyDataSetChanged()刷新。