View编程(2): invalidate()再探

博客 Android(四) :更新UI的方法 中提到invalidate()方法,但是由于自己的阅历不足,没有过多的说明,只是泛泛而谈!本篇继续探究这个诡异的方法。


在阅读本篇博客之前,建议您先看看 View编程(1): Window、View与setContentView()


基于 Android(四) :更新UI的方法 中的例子,稍作修改:

package mark.zhang;

import android.app.Activity;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.RectF;
import android.os.Bundle;
import android.util.Log;
import android.view.View;

public class ViewDrawTestActivity extends Activity {
	// 用于测试
	static int times = 1;

	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(new MyView(this));
	}
	
	/**
	 * 内部类,继承View
	 * 
	 * @author mark
	 */
	class MyView extends View {

		MyView(Context context) {
			super(context);
		}
		Paint vPaint = new Paint(); // 绘制样式物件
		int i = 0; // 弧形角度
		@Override
		protected void onDraw(Canvas canvas) {
			super.onDraw(canvas);
			Log.d("mark", "this run onDraw() " + (times++) + " times!");
			// 设定绘图样式
			vPaint.setColor(0xff00ffff); // 画笔颜色
			vPaint.setAntiAlias(true); // 反锯齿
			vPaint.setStyle(Paint.Style.STROKE);
			// 绘制一个弧形
			canvas.drawArc(new RectF(60, 120, 260, 320), 0, i, true, vPaint);
			// 弧形角度
			if ((i += 10) > 360)
				i = 0;
			// 重绘, 再一次执行onDraw 程序
			//invalidate();
		}
	}
}
运行效果:

可以看出,图像只画了一条线,说明onDraw()方法被调用一次。从log上也可以看出来:

D/mark    (  221): this run onDraw() 1 times!
那么,是什么力量促使onDraw()方法被调用呢?

setContentView()View view方法,其实是调用PhoneWindow的setContentView(View view)方法,调用关系如下:


从而可以看出,invalidate()方法是促使onDraw()方法被调用的力量。
那么,修改代码,将内部类MyView的onDraw()方法中的invalidate()注释取消,再看看运行效果:



控制台:

D/mark    (  248): this run onDraw() 5629 times!
D/mark    (  248): this run onDraw() 5630 times!
D/mark    (  248): this run onDraw() 5631 times!
D/mark    (  248): this run onDraw() 5632 times!
D/mark    (  248): this run onDraw() 5633 times!
D/mark    (  248): this run onDraw() 5634 times!
D/mark    (  248): this run onDraw() 5635 times!
D/mark    (  248): this run onDraw() 5636 times!
D/mark    (  248): this run onDraw() 5637 times!
D/mark    (  248): this run onDraw() 5638 times!
D/mark    (  248): this run onDraw() 5639 times!
D/mark    (  248): this run onDraw() 5640 times!
D/mark    (  248): this run onDraw() 5641 times!
D/mark    (  248): this run onDraw() 5642 times!
D/mark    (  248): this run onDraw() 5643 times!
D/mark    (  248): this run onDraw() 5644 times!
D/mark    (  248): this run onDraw() 5645 times!
D/mark    (  248): this run onDraw() 5646 times!
可以看出,invalidate()方法使onDraw()一直被调用,实现重绘的效果。

在invalidate()方法源码中,有这么一段注释:

 /**
     * Invalidate the whole view. If the view is visible, {@link #onDraw} will
     * be called at some point in the future. This must be called from a
     * UI thread. To call from a non-UI thread, call {@link #postInvalidate()}.
     */

这段话,说明了上面的实现(调用onDraw()方法)。但是在子线程中必须使用postInvalidate()方法。


如果有兴趣的话,请接着看 View编程(3): invalidate()源码分析








©️2020 CSDN 皮肤主题: 酷酷鲨 设计师:CSDN官方博客 返回首页