项目地址github
首先打开overdraw view,然后进入我们的MainActivity,如下:
红色是过度绘制严重的区域,我们打开布局文件看看
很容易就看到了一块区域的背景重复绘制了,我们把里层的删掉
变绿了。。好了很多,我们再来优化一下视图层级,采用RelativeLayout布局试试,优化之前先打开GPU Profiler检测一下当前的视图渲染时间,如图
修改后的XML文件:
满怀信心的运行:
卧槽,你TM还突破天际了?看来老师说的根布局尽量不用用RelativeLayout是真的T T
那么就不改根布局了,把ImageView那块用RelativeLayout吧
看着舒服了很多。。虽然并没有什么卵用,GPU Profiler依然要上天
MainActivity就到此为止吧,桑心。接下来看看OverDrawViewActivity
非常恐怖!马上点开XML看一下,结果XML里什么都没有!只有一个自定义View,我们打开这个OverDrawView看一下,重点在onDraw方法
可以看出,这里的Rect一层一层叠加,导致了过度绘制,我们先分析一下
这张图应该能说明问题了吧,好了接下来就是修改(简单的数学计算):
// 该区域最终只漏出了height/4的高度,所以修改一下高度,后面几个同理
mPaint.setColor(Color.GRAY);
// canvas.drawRect(0, 0, width, height, mPaint);
canvas.drawRect(0, 0, width, height / 4, mPaint);
mPaint.setColor(Color.CYAN);
// canvas.drawRect(0, height/4, width, height, mPaint);
canvas.drawRect(0, height/4, width, height / 3, mPaint);
mPaint.setColor(Color.DKGRAY);
// canvas.drawRect(0, height/3, width, height, mPaint);
canvas.drawRect(0, height/3, width, height / 2 , mPaint);
mPaint.setColor(Color.LTGRAY);
canvas.drawRect(0, height/2, width, height, mPaint);
最终效果:
接下来再看看BusyOnDrawActivity,点击按钮进入这个Activity时非常卡,用了差不多2s才进去,
快速上下滑动是这样的:
Activity代码里什么都没有,然后我们看看XML布局
布局很简单,就是一个ScrollView里面套着一堆园,数了一下总共10行,每行3个,每个圆宽高都是100dp。这个圆就是一个自定义View 叫BusyOnDrawView,我们进去看看:
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
for (int i = 0; i < 1000; i++) {
System.out.println("canvas = [" + canvas + "]" + i);
}
Paint paint = new Paint();
paint.setColor(Color.RED);
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeWidth(4);
int radius = Math.min(getWidth(), getHeight()) / 2;
canvas.drawCircle(getWidth()/2, getHeight()/2, radius, paint);
}
这里打印一堆log不知道是干嘛的,注掉,然后运行,发现瞬间不卡了。然后再把Paint提出来。然后再把计算radius提取成成员变量,获取尺寸都移动到onSizeChanged方法中。最终代码如下
public class BusyOnDrawView extends View {
private Paint mPaint;
private int mRadius;
private int mWidth;
private int mHeight;
public BusyOnDrawView(Context context) {
super(context);
init();
}
public BusyOnDrawView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public BusyOnDrawView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
public BusyOnDrawView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
init();
}
private void init() {
mPaint = new Paint();
mPaint.setColor(Color.RED);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeWidth(4);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
// for (int i = 0; i < 1000; i++) {
// System.out.println("canvas = [" + canvas + "]" + i);
// }
canvas.drawCircle(mWidth/2, mHeight/2, mRadius, mPaint);
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
mWidth = getWidth();
mHeight = getHeight();
mRadius = Math.min(mWidth, mHeight) / 2;
}
}
这里我觉得用RecyclerView是否更好?我们修改一下布局和代码。突然发现RecyclerView还得导依赖,这里就偷懒用一下ListView吧,一个意思。
public class BusyOnDrawViewActivity extends AppCompatActivity {
private ListView mListView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_busy_on_draw_view);
mListView = (ListView) findViewById(R.id.lv);
mListView.setAdapter(new MyAdapter());
}
class MyAdapter extends BaseAdapter {
@Override
public int getCount() {
return 10;
}
@Override
public Object getItem(int position) {
return null;
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
if (convertView == null) {
convertView = LayoutInflater.from(parent.getContext())
.inflate(R.layout.item, parent, false);
}
return convertView;
}
}
}
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin">
<ListView
android:id="@+id/lv"
android:divider="@null"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</LinearLayout>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<com.github.lzyzsd.androiduiproblems.BusyOnDrawView
android:layout_width="100dp"
android:layout_height="100dp"/>
<com.github.lzyzsd.androiduiproblems.BusyOnDrawView
android:layout_width="100dp"
android:layout_height="100dp"/>
<com.github.lzyzsd.androiduiproblems.BusyOnDrawView
android:layout_width="100dp"
android:layout_height="100dp"/>
</LinearLayout>
全文完