android 双缓冲机制

来源:互联网 发布:呼伦贝尔盟616事件知乎 编辑:程序博客网 时间:2024/05/22 00:07

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

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,然后再主线程中捕获、处理该消息。

 

Java代码  收藏代码
  1. /** 
  2.  * 要在Activity中开启一个用于更新的线程 
  3.  * timeViewHandler 继承自Handler,用于处理和发送消息 
  4.  * MSG_UPDATE 是自定义的一个int常量,用于区分消息类型,可自由取值。 
  5.  */  
  6. new Thread(new Runnable() {  
  7.     @Override  
  8.     public void run() {  
  9.         while(true){  
  10.             try {  
  11.                 timeViewHandler.sendMessage(Message.obtain(timeViewHandler, MSG_UPDATE));  
  12.                 Thread.sleep(1000);  
  13.             } catch (InterruptedException e) {  
  14.                 e.printStackTrace();  
  15.             }   
  16.         }  
  17.     }  
  18. }).start();  
 
Java代码  收藏代码
  1. /** 
  2.  * Handler示例,用于刷新时间 
  3.  * DateHelper是我自己写的日期格式化工具哦 
  4.  * @author Dreamworker 
  5.  * 
  6.  */  
  7. public class TimeViewHandler extends Handler {  
  8.     private TextView timeView;  
  9.       
  10.     public TextView getTimeView() {  
  11.         return timeView;  
  12.     }  
  13.   
  14.     public void setTimeView(TextView timeView) {  
  15.         this.timeView = timeView;  
  16.     }  
  17.   
  18.     public TimeViewHandler(TextView timeView) {  
  19.         super();  
  20.         this.timeView = timeView;  
  21.     }  
  22.   
  23.     @Override  
  24.     public void handleMessage(Message msg) {  
  25.         switch (msg.what) {  
  26.             case MSG_UPDATE:  
  27.                 timeView.setText(DateHelper.getNow("kk:mm:ss"));  
  28.                 timeView.invalidate();  
  29.                 break;  
  30.         }  
  31.         super.handleMessage(msg);  
  32.     }  
  33.       
  34. }  
 


3.使用多线程和双缓冲

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

Java代码  收藏代码
  1. /** 
  2. * SurfaceView使用示例,TouchDrawView主要完成屏幕的指尖绘画 
  3. * TouchDrawListener是我自己写的监听器,就不妨碍大家视线了。 
  4. */  
  5. public class TouchDrawView extends SurfaceView implements SurfaceHolder.Callback{  
  6.     private SurfaceHolder holder;  
  7.     private TouchDrawListener listener;  
  8.   
  9.     public TouchDrawListener getListener() {  
  10.         return listener;  
  11.     }  
  12.   
  13.     public void setListener(TouchDrawListener listener) {  
  14.         this.listener = listener;  
  15.     }  
  16.   
  17.     public TouchDrawView(Context context) {  
  18.         super(context);  
  19.         holder = getHolder();  
  20.         holder.addCallback(this);  
  21.         listener = new TouchDrawListener(holder);  
  22.         listener.setShape(TouchDrawListener.SHAPE_LINE);  
  23.         listener.setShape_style(TouchDrawListener.SHAPE_STYLE_FILL);  
  24.         this.setOnTouchListener(listener);//设置屏幕事件监听器  
  25.         this.setLongClickable(true);//不设置将无法捕捉onFling()事件  
  26.         setFocusable(true);//设置键盘焦点  
  27.         setFocusableInTouchMode(true);//设置触摸屏焦点  
  28.     }  
  29.       
  30.     public TouchDrawView(Context context, AttributeSet as) {  
  31.         this(context);  
  32.     }  
  33.   
  34.     @Override  
  35.     protected void onDraw(Canvas canvas) {    
  36.   
  37.     }  
  38.       
  39.     @Override  
  40.     public void surfaceChanged(SurfaceHolder holder, int format, int width,  
  41.             int height) {  
  42.           
  43.     }  
  44.   
  45.     @Override  
  46.     public void surfaceCreated(SurfaceHolder holder) {  
  47.   
  48.                  //关键部分  
  49.         Canvas canvas = holder.lockCanvas(null);//获取画布    
  50.         canvas.drawColor(Color.WHITE);//白色背景  
  51.         holder.unlockCanvasAndPost(canvas);//解锁画布,提交画好的图像    
  52.     }  
  53.   
  54.     @Override  
  55.     public void surfaceDestroyed(SurfaceHolder holder) {  
  56.           
  57.     }  
  58. }  
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 cad图全部倒过来了怎么办 电脑打数字变粗怎么办 wps表格输入数字变乱码怎么办 文档中光标变粗怎么办 wps排序有重复的怎么办 记英语数字老是混怎么办 苹果手机输入法出数字怎么办 word文档复制过来有底色怎么办 表格复制后还再显示复制符号怎么办 笔记本字母键打出数字怎么办 wps打字字上移了怎么办 微信里黑圈里面的白字是怎么办 脖子比脸黑好多怎么办 河南许昌小学生生病办休学怎么办 1岁宝宝内向胆小怎么办 3岁宝宝内向胆小怎么办 数学物理好不喜欢学医怎么办 孩子眉毛太浓了怎么办 小娃一年级成绩太差怎么办 孩子晚上睡得晚怎么办 在深圳买房难小孩读书怎么办 上海小孩读书积分不够怎么办 读书时静不下心怎么办 初中生静不下心读书怎么办 孩子学习静不下心怎么办 退烧后体温35度怎么办 孩子体温34度多怎么办 宝宝感冒咳嗽流鼻涕出汗怎么办 养的小鸡总打架怎么办 小鸡一条腿瘸了怎么办 同窝小斗鸡打架怎么办 夏季羊长的慢怎么办 1岁吃母乳不吃饭怎么办 5个月宝宝黏妈妈怎么办 九个月宝宝不爱吃饭怎么办 20个月宝宝吐了怎么办 十个月的宝宝消化不好怎么办 两岁宝宝不爱喝水怎么办 两岁宝宝不爱喝水吃饭怎么办 两岁的宝宝不爱喝水怎么办 宝宝不爱吃饭不爱喝水怎么办