Android中UI(View)的刷新

看了很多资料,翻啊翻啊,似乎有些了解了。

Android中对View的更新有很多种方式,使用时要区分不同的应用场合。我感觉最要紧的是分清:多线程和双缓冲的使用情况。


现在可以尝试理解下面的模拟场景:

        两个人:一对夫妻,老公上班,老婆在家,现在他们都要吃饭。

     “不使用多线程和双缓冲”的情况是:老公在公司吃,老婆在家吃,互不干扰,吃就是了。

     “使用多线程和不使用双缓冲”的情况是:老婆做好饭,另外让人送一份到公司,老公收到饭就可以吃了。

     “使用多线程和使用双缓冲”的情况是:老婆做好饭,等老公回家一起吃。


1.不使用多线程和双缓冲

     这种情况最简单了,一般只是希望在View发生改变时对UI进行重绘。你只需在Activity中显式地调用View对象中的invalidate()方法即可。系统会自动调用 View的onDraw()方法。


2.使用多线程和不使用双缓冲

     这种情况需要开启新的线程,新开的线程就不好访问View对象了。强行访问的话会报:android.view.ViewRoot$CalledFromWrongThreadException:Only the original thread that created a view hierarchy can touch its views.

     这时候你需要创建一个继承了android.os.Handler的子类,并重写handleMessage(Message msg)方法。android.os.Handler是能发送和处理消息的,你需要在Activity中发出更新UI的消息,然后再你的Handler(可以使用匿名内部类)中处理消息(因为匿名内部类可以访问父类变量, 你可以直接调用View对象中的invalidate()方法 )。也就是说:在新线程创建并发送一个Message,然后再主线程中捕获、处理该消息。

 

/**
 * 要在Activity中开启一个用于更新的线程
 * timeViewHandler 继承自Handler,用于处理和发送消息
 * MSG_UPDATE 是自定义的一个int常量,用于区分消息类型,可自由取值。
 */
new Thread(new Runnable() {
	@Override
	public void run() {
		while(true){
			try {
				timeViewHandler.sendMessage(Message.obtain(timeViewHandler, MSG_UPDATE));
				Thread.sleep(1000);
			} catch (InterruptedException e) {
				e.printStackTrace();
			} 
		}
	}
}).start();
 
/**
 * Handler示例,用于刷新时间
 * DateHelper是我自己写的日期格式化工具哦
 * @author Dreamworker
 *
 */
public class TimeViewHandler extends Handler {
	private TextView timeView;
	
	public TextView getTimeView() {
		return timeView;
	}

	public void setTimeView(TextView timeView) {
		this.timeView = timeView;
	}

	public TimeViewHandler(TextView timeView) {
		super();
		this.timeView = timeView;
	}

	@Override
	public void handleMessage(Message msg) {
		switch (msg.what) {
			case MSG_UPDATE:
				timeView.setText(DateHelper.getNow("kk:mm:ss"));
				timeView.invalidate();
				break;
		}
		super.handleMessage(msg);
	}
	
}
 


3.使用多线程和双缓冲

    Android中SurfaceView是View的子类,她同时也实现了双缓冲。你可以定义一个她的子类并实现SurfaceHolder.Callback接口。由于实现SurfaceHolder.Callback接口,新线程就不需要android.os.Handler帮忙了。SurfaceHolder中lockCanvas()方法可以锁定画布,绘制玩新的图像后调用unlockCanvasAndPost(canvas)解锁(显示),还是比较方便得。

/**
* SurfaceView使用示例,TouchDrawView主要完成屏幕的指尖绘画
* TouchDrawListener是我自己写的监听器,就不妨碍大家视线了。
*/
public class TouchDrawView extends SurfaceView implements SurfaceHolder.Callback{
	private SurfaceHolder holder;
	private TouchDrawListener listener;

	public TouchDrawListener getListener() {
		return listener;
	}

	public void setListener(TouchDrawListener listener) {
		this.listener = listener;
	}

	public TouchDrawView(Context context) {
		super(context);
		holder = getHolder();
		holder.addCallback(this);
		listener = new TouchDrawListener(holder);
		listener.setShape(TouchDrawListener.SHAPE_LINE);
		listener.setShape_style(TouchDrawListener.SHAPE_STYLE_FILL);
		this.setOnTouchListener(listener);//设置屏幕事件监听器
		this.setLongClickable(true);//不设置将无法捕捉onFling()事件
		setFocusable(true);//设置键盘焦点
		setFocusableInTouchMode(true);//设置触摸屏焦点
	}
	
	public TouchDrawView(Context context, AttributeSet as) {
		this(context);
	}

	@Override
	protected void onDraw(Canvas canvas) {	

	}
	
	@Override
	public void surfaceChanged(SurfaceHolder holder, int format, int width,
			int height) {
		
	}

	@Override
	public void surfaceCreated(SurfaceHolder holder) {

                 //关键部分
		Canvas canvas = holder.lockCanvas(null);//获取画布  
		canvas.drawColor(Color.WHITE);//白色背景
		holder.unlockCanvasAndPost(canvas);//解锁画布,提交画好的图像  
	}

	@Override
	public void surfaceDestroyed(SurfaceHolder holder) {
		
	}
}
 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值