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

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. }  

更多相关文章

  1. Android 性能优化——通过线程提高性能
  2. [置顶] 在单线程模型中Message、Handler、Message Queue、Looper
  3. Android多线程问题
  4. Android Handler 主线程 子线程 双向通信
  5. Android 之多线程下载原理
  6. Android碎碎念 -- 性能测试,适用于Android Studio的代码审查和性
  7. 对系统学习与写博客的看法——学完《第一行代码》有感

随机推荐

  1. 直播软件开发Android项目之视频播放器
  2. android 中SQLite数据库多条插入如何提高
  3. Android处理非res资源的例子
  4. Android中全屏 及 去掉标题栏
  5. 如何更改Android(安卓)程序的icon快捷方
  6. Android系统文件夹结构
  7. Android(安卓)—— TextView中的MaxLines
  8. 歌词效果制作
  9. Android开发之获取网络类型(WIFI、2G、3G
  10. 继续分享12个亲测源码