項目地址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>
全文完