技术咨询、项目合作、广告投放、简历咨询、技术文档下载
点击这里 联系博主
# 合理的刷新机制
在应用的开发中,因为数据的变化,需要刷新页面来展示数据,但是频繁的刷新会增加资源的开销,并且可能导致卡顿。 合理的刷新机制需要注意以下几点:
- 尽量减少刷新的次数
- 尽量避免后台有高 CPU 线程运行
- 缩小刷新区域
# 一、减少刷新次数
- 控制刷新的频率 比如在显示进度条的时候,不需要每一个进度的时候都需要显示,可以做到每隔多少刷新显示一次,这样就减少了刷新的频率。
- 避免没有必要的刷新 首先需要判断是否需要刷新,比如数据没有变化的时候,需要刷新的控件不在可见区域内,就没必要刷新,但是需要注意的是:如果一个 View 从不可见到可见,一定要刷新一次。
# 二、避免后台线程影响
后台线程过大会导致 CPU 占比过高,导致频繁的 GC 和 CPU 时间片资源紧张,还是优肯会导致页面的卡顿。比如在 RecyclerView 或者 ListView 在滑动的时候就可以暂停其他的 UI 操作: 通过监听 ListView 的 onScrollStateChanged 事件,在滚动的时候暂停下载图片和下载进程工作,结束后再刷新可以提高 ListView 的滑动平滑度。(具体详见:Android 缓存策略和 Bitmap 高效加载)。
# 三、缩小刷新的区域
# 在自定义 View
中
在自定义 View 中一般采用 invalidata
方法刷新,如果需要更新数据,只是在某个区域的话,在调用了 invalidata
就会更新整个视图,这就浪费了不需要更新区域的资源。我们采用两种更新局部数据的方法。
invalidata(Rect dirty)
invalidata(int left,int top,int right,int bottom)
# 容器中的某个 Item 发生了变化
只需要更新这个 Item 就行了。比如在 ListView
中或者 RecyclerView
中,如果是单条操作,就必须调用 Adapter
的 notifyDataChanged
()刷新。
# invalidate()函数的区域更新例子
public class FingerView extends View {
private static final float STROKE_WIDTH = 5f;
/** Need to track this so the dirty region can accommodate the stroke. **/
private static final float HALF_STROKE_WIDTH = STROKE_WIDTH / 2;
private Paint paint = new Paint();
private Path path = new Path();
/**
* Optimizes painting by invalidating the smallest possible area.
*/
private float lastTouchX;
private float lastTouchY;
private final RectF dirtyRect = new RectF();
public <span style="font-family: Arial, Helvetica, sans-serif; font-size: ;">FingerView </span>(Context context, AttributeSet attrs) {
super(context, attrs);
paint.setAntiAlias(true);
paint.setColor(Color.BLACK);
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeJoin(Paint.Join.ROUND);
paint.setStrokeWidth(STROKE_WIDTH);
}
/**
* Erases the signature.
*/
public void clear() {
path.reset();
// Repaints the entire view.
invalidate();
}
@Override
protected void onDraw(Canvas canvas) {
canvas.drawPath(path, paint);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
float eventX = event.getX();
float eventY = event.getY();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
path.moveTo(eventX, eventY);
lastTouchX = eventX;
lastTouchY = eventY;
// There is no end point yet, so don't waste cycles invalidating.
return true;
case MotionEvent.ACTION_MOVE:
case MotionEvent.ACTION_UP:
// Start tracking the dirty region.
resetDirtyRect(eventX, eventY);
// When the hardware tracks events faster than they are delivered,
// event will contain a history of those skipped points.
int historySize = event.getHistorySize();
for (int i = 0; i < historySize; i++) {
float historicalX = event.getHistoricalX(i);
float historicalY = event.getHistoricalY(i);
expandDirtyRect(historicalX, historicalY);
path.lineTo(historicalX, historicalY);
}
// After replaying history, connect the line to the touch point.
path.lineTo(eventX, eventY);
break;
default:
debug("Ignored touch event: " + event.toString());
return false;
}
// Include half the stroke width to avoid clipping.
invalidate(
(int) (dirtyRect.left - HALF_STROKE_WIDTH),
(int) (dirtyRect.top - HALF_STROKE_WIDTH),
(int) (dirtyRect.right + HALF_STROKE_WIDTH),
(int) (dirtyRect.bottom + HALF_STROKE_WIDTH));
lastTouchX = eventX;
lastTouchY = eventY;
return true;
}
/**
* Called when replaying history to ensure the dirty region includes all
* points.
*/
private void expandDirtyRect(float historicalX, float historicalY) {
if (historicalX < dirtyRect.left) {
dirtyRect.left = historicalX;
} else if (historicalX > dirtyRect.right) {
dirtyRect.right = historicalX;
}
if (historicalY < dirtyRect.top) {
dirtyRect.top = historicalY;
} else if (historicalY > dirtyRect.bottom) {
dirtyRect.bottom = historicalY;
}
}
/**
* Resets the dirty region when the motion event occurs.
*/
private void resetDirtyRect(float eventX, float eventY) {
// The lastTouchX and lastTouchY were set when the ACTION_DOWN
// motion event occurred.
dirtyRect.left = Math.min(lastTouchX, eventX);
dirtyRect.right = Math.max(lastTouchX, eventX);
dirtyRect.top = Math.min(lastTouchY, eventY);
dirtyRect.bottom = Math.max(lastTouchY, eventY);
}
}
- 本文链接: https://mrgaogang.github.io/android/performance/%E5%90%88%E7%90%86%E7%9A%84%E5%88%B7%E6%96%B0%E6%9C%BA%E5%88%B6.html
- 版权声明: 本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 许可协议。转载请注明出处!
← Android性能优化之绘制优化 布局优化 →