`
jandroid
  • 浏览: 1894266 次
  • 性别: Icon_minigender_1
  • 来自: 北京
文章分类
社区版块
存档分类
最新评论

Android提高第三篇之SurfaceView(下)

阅读更多

简 单介绍了SurfaceView的使用,这次就介绍SurfaceView的双缓冲使用。双缓冲是为了防止动画闪烁而实现的一种多线程应用,基于 SurfaceView的双缓冲实现很简单,开一条线程并在其中绘图即可。本文介绍基于SurfaceView的双缓冲实现,以及介绍类似的更高效的实现 方法。

        本文程序运行截图如下,左边是开单个线程读取并绘图,右边是开两个线程,一个专门读取图片,一个专门绘图:

对 比一下,右边动画的帧速明显比左边的快,左右两者都没使用Thread.sleep()。为什么要开两个线程一个读一个画,而不去开两个线程像左边那样都 “边读边画”呢?因为SurfaceView每次绘图都会锁定Canvas,也就是说同一片区域这次没画完下次就不能画,因此要提高双缓冲的效率,就得开一条线程专门画图,开另外一条线程做预处理的工作。

main.xml的源码:

  1. <? xml   version = "1.0"   encoding = "utf-8" ?>   
  2. < LinearLayout   xmlns:android = "http://schemas.android.com/apk/res/android"   
  3.     android:layout_width = "fill_parent"   android:layout_height = "fill_parent"   
  4.     android:orientation = "vertical" >   
  5.   
  6.     < LinearLayout   android:id = "@+id/LinearLayout01"   
  7.         android:layout_width = "wrap_content"   android:layout_height = "wrap_content" >   
  8.         < Button   android:id = "@+id/Button01"   android:layout_width = "wrap_content"   
  9.             android:layout_height = "wrap_content"   android:text = "单个独立线程" > </ Button >   
  10.         < Button   android:id = "@+id/Button02"   android:layout_width = "wrap_content"   
  11.             android:layout_height = "wrap_content"   android:text = "两个独立线程" > </ Button >   
  12.     </ LinearLayout >   
  13.     < SurfaceView   android:id = "@+id/SurfaceView01"   
  14.         android:layout_width = "fill_parent"   android:layout_height = "fill_parent" > </ SurfaceView >   
  15. </ LinearLayout >   

本文程序的源码:

 

  1. package  com.testSurfaceView;  
  2.   
  3. import  java.lang.reflect.Field;  
  4. import  java.util.ArrayList;  
  5. import  android.app.Activity;  
  6. import  android.graphics.Bitmap;  
  7. import  android.graphics.BitmapFactory;  
  8. import  android.graphics.Canvas;  
  9. import  android.graphics.Paint;  
  10. import  android.graphics.Rect;  
  11. import  android.os.Bundle;  
  12. import  android.util.Log;  
  13. import  android.view.SurfaceHolder;  
  14. import  android.view.SurfaceView;  
  15. import  android.view.View;  
  16. import  android.widget.Button;  
  17.   
  18. public   class  testSurfaceView  extends  Activity {  
  19.     /** Called when the activity is first created. */   
  20.     Button btnSingleThread, btnDoubleThread;  
  21.     SurfaceView sfv;  
  22.     SurfaceHolder sfh;  
  23.     ArrayList<Integer> imgList = new  ArrayList<Integer>();  
  24.     int  imgWidth, imgHeight;  
  25.     Bitmap bitmap;//独立线程读取,独立线程绘图   
  26.   
  27.     @Override   
  28.     public   void  onCreate(Bundle savedInstanceState) {  
  29.         super .onCreate(savedInstanceState);  
  30.         setContentView(R.layout.main);  
  31.   
  32.         btnSingleThread = (Button) this .findViewById(R.id.Button01);  
  33.         btnDoubleThread = (Button) this .findViewById(R.id.Button02);  
  34.         btnSingleThread.setOnClickListener(new  ClickEvent());  
  35.         btnDoubleThread.setOnClickListener(new  ClickEvent());  
  36.         sfv = (SurfaceView) this .findViewById(R.id.SurfaceView01);  
  37.         sfh = sfv.getHolder();  
  38.         sfh.addCallback(new  MyCallBack()); // 自动运行surfaceCreated以及surfaceChanged   
  39.     }  
  40.   
  41.     class  ClickEvent  implements  View.OnClickListener {  
  42.   
  43.         @Override   
  44.         public   void  onClick(View v) {  
  45.   
  46.             if  (v == btnSingleThread) {  
  47.                 new  Load_DrawImage( 0 0 ).start(); //开一条线程读取并绘图   
  48.             } else   if  (v == btnDoubleThread) {  
  49.                 new  LoadImage().start(); //开一条线程读取   
  50.                 new  DrawImage(imgWidth +  10 0 ).start(); //开一条线程绘图   
  51.             }  
  52.   
  53.         }  
  54.   
  55.     }  
  56.   
  57.     class  MyCallBack  implements  SurfaceHolder.Callback {  
  58.   
  59.         @Override   
  60.         public   void  surfaceChanged(SurfaceHolder holder,  int  format,  int  width,  
  61.                 int  height) {  
  62.             Log.i("Surface:" "Change" );  
  63.   
  64.         }  
  65.   
  66.         @Override   
  67.         public   void  surfaceCreated(SurfaceHolder holder) {  
  68.             Log.i("Surface:" "Create" );  
  69.   
  70.             // 用反射机制来获取资源中的图片ID和尺寸   
  71.             Field[] fields = R.drawable.class .getDeclaredFields();  
  72.             for  (Field field : fields) {  
  73.                 if  (! "icon" .equals(field.getName())) // 除了icon之外的图片   
  74.                 {  
  75.                     int  index =  0 ;  
  76.                     try  {  
  77.                         index = field.getInt(R.drawable.class );  
  78.                     } catch  (IllegalArgumentException e) {  
  79.                         // TODO Auto-generated catch block   
  80.                         e.printStackTrace();  
  81.                     } catch  (IllegalAccessException e) {  
  82.                         // TODO Auto-generated catch block   
  83.                         e.printStackTrace();  
  84.                     }  
  85.                     // 保存图片ID   
  86.                     imgList.add(index);  
  87.                 }  
  88.             }  
  89.             // 取得图像大小   
  90.             Bitmap bmImg = BitmapFactory.decodeResource(getResources(),  
  91.                     imgList.get(0 ));  
  92.             imgWidth = bmImg.getWidth();  
  93.             imgHeight = bmImg.getHeight();  
  94.         }  
  95.   
  96.         @Override   
  97.         public   void  surfaceDestroyed(SurfaceHolder holder) {  
  98.             Log.i("Surface:" "Destroy" );  
  99.   
  100.         }  
  101.   
  102.     }  
  103.   
  104.     /*  
  105.      * 读取并显示图片的线程  
  106.      */   
  107.     class  Load_DrawImage  extends  Thread {  
  108.         int  x, y;  
  109.         int  imgIndex =  0 ;  
  110.   
  111.         public  Load_DrawImage( int  x,  int  y) {  
  112.             this .x = x;  
  113.             this .y = y;  
  114.         }  
  115.   
  116.         public   void  run() {  
  117.             while  ( true ) {  
  118.                 Canvas c = sfh.lockCanvas(new  Rect( this .x,  this .y,  this .x  
  119.                         + imgWidth, this .y + imgHeight));  
  120.                 Bitmap bmImg = BitmapFactory.decodeResource(getResources(),  
  121.                         imgList.get(imgIndex));  
  122.                 c.drawBitmap(bmImg, this .x,  this .y,  new  Paint());  
  123.                 imgIndex++;  
  124.                 if  (imgIndex == imgList.size())  
  125.                     imgIndex = 0 ;  
  126.   
  127.                 sfh.unlockCanvasAndPost(c);// 更新屏幕显示内容   
  128.             }  
  129.         }  
  130.     };  
  131.   
  132.     /*  
  133.      * 只负责绘图的线程  
  134.      */   
  135.     class  DrawImage  extends  Thread {  
  136.         int  x, y;  
  137.   
  138.         public  DrawImage( int  x,  int  y) {  
  139.             this .x = x;  
  140.             this .y = y;  
  141.         }  
  142.   
  143.         public   void  run() {  
  144.             while  ( true ) {  
  145.                 if  (bitmap !=  null ) { //如果图像有效   
  146.                     Canvas c = sfh.lockCanvas(new  Rect( this .x,  this .y,  this .x  
  147.                             + imgWidth, this .y + imgHeight));  
  148.   
  149.                     c.drawBitmap(bitmap, this .x,  this .y,  new  Paint());  
  150.   
  151.                     sfh.unlockCanvasAndPost(c);// 更新屏幕显示内容   
  152.                 }  
  153.             }  
  154.         }  
  155.     };  
  156.   
  157.     /*  
  158.      * 只负责读取图片的线程  
  159.      */   
  160.     class  LoadImage  extends  Thread {  
  161.         int  imgIndex =  0 ;  
  162.   
  163.         public   void  run() {  
  164.             while  ( true ) {  
  165.                 bitmap = BitmapFactory.decodeResource(getResources(),  
  166.                         imgList.get(imgIndex));  
  167.                 imgIndex++;  
  168.                 if  (imgIndex == imgList.size()) //如果到尽头则重新读取   
  169.                     imgIndex = 0 ;  
  170.             }  
  171.         }  
  172.     };  

分享到:
评论

相关推荐

    Android提高第三篇之SurfaceView与多线程的混搭.docx

    Android提高第三篇之SurfaceView与多线程的混搭.docx

    Android中SurfaceView截屏

    这是在上网收集的,能够截取当前Activity中surfaceView中图片。本人亲测可以通过。

    android上下滑动引导页 上下切换页面 手势判断 SurfaceView实现

    android上下滑动引导页 上下切换页面 手势判断 SurfaceView实现,不使用任何第三方jar包 安卓上下滑动引导页面 一次切换一个页面

    Android代码-经典跑酷

    从12年初(大二上学期)开始自学Java,12年9月份(大二下学期)开始自学Android,然后历时近三个月,在一边学一边写中完成了这个用SurfaceView写的跑酷游戏。 同时拿这个作品参加了2013年的谷歌安卓第四届大学生挑战...

    android开发揭秘PDF

    第3章 Android程序设计基础 3.1 Android程序框架 3.1.1 Android项目目录结构 3.1.2 Android应用解析 3.2 Android的生命周期 3.3 Android程序U设计 3.4 小结 第4章 用户界面开发 4.1 用户界面开发详解 4.1.1 用户...

    《Android应用开发揭秘》附带光盘代码.

     第3章 Android程序设计基础  3.1 Android程序框架  3.1.1 Android项目目录结构  3.1.2 Android应用解析  3.2 Android的生命周期  3.3 Android程序U设计  3.4 小结  第4章 用户界面开发  4.1 用户界面开发...

    Android应用开发揭秘pdf高清版

    第3章 Android程序设计基础 3.1 Android程序框架 3.1.1 Android项目目录结构 3.1.2 Android应用解析 3.2 Android的生命周期 3.3 Android程序U设计 3.4 小结 第4章 用户界面开发 4.1 用户界面开发详解 4.1.1 用户...

    《Android应用开发揭秘》源码

     第3章 Android程序设计基础  3.1 Android程序框架  3.1.1 Android项目目录结构  3.1.2 Android应用解析  3.2 Android的生命周期  3.3 Android程序U设计  3.4 小结  第4章 用户界面开发  4.1 用户界面开发...

    从零开始Android游戏编程电子书 word之Docx版

    第三章 显示文字和图片.docx 第四章 响应用户事件.docx 第五章 小结——扫雷游戏的实现.docx 第六章 SurfaceView动画.docx 第七章 精灵、帧动画与碰撞检测.docx 第八章 地图的设计和实现.docx 第九章 游戏程序...

    Google Android SDK开发范例大全(第3版)part2

     第3章 用户人机界面  3.1 更改与显示文字标签  3.2 更改手机窗口画面底色  3.3 更改TextView文字颜色  3.4 置换TextView文字  3.5 取得手机屏幕大小  3.6 样式化的定型对象  3.7 简易的按钮事件  ...

    《Android高级编程》

    2.5 小结 第3章 创建应用程序和活动 3.1 Android应用程序的组成部分 3.2 程序清单简介 3.3 使用清单编辑器 3.4 Android应用程序生命周期 3.5 理解应用程序的优先级和进程状态 3.6 分离资源 3.6.1 创建资源 3.6.2 ...

    Android 仿抖音APP下拉刷新功能.rar

    Android 仿抖音APP下拉刷新功能,首先分析这个效果的实现思路,大致如下:  1、上拉时页面有翻页效果,可以用scrollview的pagingEnabled来实现,也就是说列表页不管你用tableview还是collectionview,只要每个cell...

    Android高级编程--源代码

    由于现有的手机应用程序的开发是构建在各手机厂家的私有操作系统之上的,所以它限制了第三方应用程序的开发,而Android为我们提供了一个开放和通用的选择。因为没有了人为制造的障碍,所以Android开发人员可以自由地...

    疯狂Android讲义源码

     第3章 事件处理 144  3.1 Android的事件处理 145  3.2 基于监听的事件处理 145  3.2.1 事件监听的处理模型 145  3.2.2 事件和事件监听器 148  3.2.3 内部类作为事件监听器类 151  3.2.4 外部类作为事件监听...

    疯狂Android讲义(第2版)源代码 第6章~第9章

    第3章、Android事件处理,包括按键响应机制和消息传递机制 3.2、基于监听器的事件处理: 3.3、基于回调的事件的处理: 3.4、响应系统设置的事件: 3.5、Handler消息传递机制: 第4章、深入理解Activity 4.1、...

    Android开发与应用——张荣,原书配套课件

    第3章 Android应用程序框架 3.1 第一个Android应用程序 3.2 Android项目结构 3.3 APK文件结构 3.4 Android应用程序权限 3.5 Activity及其生命周期 3.5.1 什么是Activity 3.5.2 Activity生命周期 3.6...

    《Google Android SDK开发范例大全(第3版)》.pdf

    第3章 用户人机界面 22 3.1 更改与显示文字标签 23 3.2 更改手机窗口画面底色 24 3.3 更改textview文字颜色 26 3.4 置换textview文字 28 3.5 取得手机屏幕大小 29 3.6 样式化的定型对象 30 ....

Global site tag (gtag.js) - Google Analytics