上一篇简单介绍了SurfaceView的使用,这次就介绍SurfaceView的双缓冲使用。双缓冲是为了防止动画闪烁而实现的一种多线程应用,基于SurfaceView的双缓冲实现很简单,开一条线程并在其中绘图即可。本文介绍基于SurfaceView的双缓冲实现,以及介绍类似的更高效的实现方法。
本文程序运行截图如下,左边是开单个线程读取并绘图,右边是开两个线程,一个专门读取图片,一个专门绘图:
对比一下,右边动画的帧速明显比左边的快,左右两者都没使用Thread.sleep()。为什么要开两个线程一个读一个画,而不去开两个线程像左边那样都“边读边画”呢?因为SurfaceView每次绘图都会锁定Canvas,也就是说同一片区域这次没画完下次就不能画,因此要提高双缓冲的效率,就得开一条线程专门画图,开另外一条线程做预处理的工作。
main.xml的源码:
- <?xmlversion="1.0"encoding="utf-8"?>
- <LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="fill_parent"android:layout_height="fill_parent"
- android:orientation="vertical">
- <LinearLayoutandroid:id="@+id/LinearLayout01"
- android:layout_width="wrap_content"android:layout_height="wrap_content">
- <Buttonandroid:id="@+id/Button01"android:layout_width="wrap_content"
- android:layout_height="wrap_content"android:text="单个独立线程"></Button>
- <Buttonandroid:id="@+id/Button02"android:layout_width="wrap_content"
- android:layout_height="wrap_content"android:text="两个独立线程"></Button>
- </LinearLayout>
- <SurfaceViewandroid:id="@+id/SurfaceView01"
- android:layout_width="fill_parent"android:layout_height="fill_parent"></SurfaceView>
- </LinearLayout>
本文程序的源码:
- packagecom.testSurfaceView;
- importjava.lang.reflect.Field;
- importjava.util.ArrayList;
- importandroid.app.Activity;
- importandroid.graphics.Bitmap;
- importandroid.graphics.BitmapFactory;
- importandroid.graphics.Canvas;
- importandroid.graphics.Paint;
- importandroid.graphics.Rect;
- importandroid.os.Bundle;
- importandroid.util.Log;
- importandroid.view.SurfaceHolder;
- importandroid.view.SurfaceView;
- importandroid.view.View;
- importandroid.widget.Button;
- publicclasstestSurfaceViewextendsActivity{
- ButtonbtnSingleThread,btnDoubleThread;
- SurfaceViewsfv;
- SurfaceHoldersfh;
- ArrayList<Integer>imgList=newArrayList<Integer>();
- intimgWidth,imgHeight;
- Bitmapbitmap;
- @Override
- publicvoidonCreate(BundlesavedInstanceState){
- super.onCreate(savedInstanceState);
- setContentView(R.layout.main);
- btnSingleThread=(Button)this.findViewById(R.id.Button01);
- btnDoubleThread=(Button)this.findViewById(R.id.Button02);
- btnSingleThread.setOnClickListener(newClickEvent());
- btnDoubleThread.setOnClickListener(newClickEvent());
- sfv=(SurfaceView)this.findViewById(R.id.SurfaceView01);
- sfh=sfv.getHolder();
- sfh.addCallback(newMyCallBack());
- }
- classClickEventimplementsView.OnClickListener{
- @Override
- publicvoidonClick(Viewv){
- if(v==btnSingleThread){
- newLoad_DrawImage(0,0).start();
- }elseif(v==btnDoubleThread){
- newLoadImage().start();
- newDrawImage(imgWidth+10,0).start();
- }
- }
- }
- classMyCallBackimplementsSurfaceHolder.Callback{
- @Override
- publicvoidsurfaceChanged(SurfaceHolderholder,intformat,intwidth,
- intheight){
- Log.i("Surface:","Change");
- }
- @Override
- publicvoidsurfaceCreated(SurfaceHolderholder){
- Log.i("Surface:","Create");
- Field[]fields=R.drawable.class.getDeclaredFields();
- for(Fieldfield:fields){
- if(!"icon".equals(field.getName()))
- {
- intindex=0;
- try{
- index=field.getInt(R.drawable.class);
- }catch(IllegalArgumentExceptione){
- e.printStackTrace();
- }catch(IllegalAccessExceptione){
- e.printStackTrace();
- }
- imgList.add(index);
- }
- }
- BitmapbmImg=BitmapFactory.decodeResource(getResources(),
- imgList.get(0));
- imgWidth=bmImg.getWidth();
- imgHeight=bmImg.getHeight();
- }
- @Override
- publicvoidsurfaceDestroyed(SurfaceHolderholder){
- Log.i("Surface:","Destroy");
- }
- }
- classLoad_DrawImageextendsThread{
- intx,y;
- intimgIndex=0;
- publicLoad_DrawImage(intx,inty){
- this.x=x;
- this.y=y;
- }
- publicvoidrun(){
- while(true){
- Canvasc=sfh.lockCanvas(newRect(this.x,this.y,this.x
- +imgWidth,this.y+imgHeight));
- BitmapbmImg=BitmapFactory.decodeResource(getResources(),
- imgList.get(imgIndex));
- c.drawBitmap(bmImg,this.x,this.y,newPaint());
- imgIndex++;
- if(imgIndex==imgList.size())
- imgIndex=0;
- sfh.unlockCanvasAndPost(c);
- }
- }
- };
- classDrawImageextendsThread{
- intx,y;
- publicDrawImage(intx,inty){
- this.x=x;
- this.y=y;
- }
- publicvoidrun(){
- while(true){
- if(bitmap!=null){
- Canvasc=sfh.lockCanvas(newRect(this.x,this.y,this.x
- +imgWidth,this.y+imgHeight));
- c.drawBitmap(bitmap,this.x,this.y,newPaint());
- sfh.unlockCanvasAndPost(c);
- }
- }
- }
- };
- classLoadImageextendsThread{
- intimgIndex=0;
- publicvoidrun(){
- while(true){
- bitmap=BitmapFactory.decodeResource(getResources(),
- imgList.get(imgIndex));
- imgIndex++;
- if(imgIndex==imgList.size())
- imgIndex=0;
- }
- }
- };
- }
分享到:
相关推荐
在本篇文章中,我们将深入探讨如何将SurfaceView与多线程相结合,以避免动画闪烁并提升性能。 首先,了解Android中多线程的基本概念。Android应用的主线程负责处理UI更新和用户交互,为了不阻塞主线程,复杂的计算...
SurfaceView 是 Android 中一种特殊的视图,它允许开发者在后台线程中进行高效、低延迟的图形绘制,特别适用于需要实时更新画面的应用场景,如游戏、视频播放等。在本文中,我们将深入探讨 SurfaceView 的基本用法和...
在Android开发中,`SurfaceView`是一个非常重要的视图组件,尤其在处理视频播放、游戏渲染等高性能图形操作时,它的优势在于拥有独立于主线程的渲染机制,能避免阻塞UI更新。然而,由于其特殊的性质,直接通过常规...
总的来说,实现"android SurfaceView做二维码扫描源码"涉及到Android的SurfaceView使用、摄像头控制、图像处理以及第三方库的集成等多个技术点。理解并掌握这些知识点,才能开发出高效稳定的二维码扫描应用。
本篇文章将深入探讨如何利用`SurfaceView`实现实时显示摄像头视频。 首先,我们需要了解`SurfaceView`的基本原理。`SurfaceView`包含一个独立的渲染表面,它位于窗口管理器的单独层上,与应用程序的其他UI组件分离...
在Android开发中,`SurfaceView`是一个非常重要的组件,它提供了与硬件图形渲染直接交互的能力。...通过理解并实践这个项目,开发者可以深入学习Android的底层图形处理以及如何利用第三方库增强应用程序的功能。
在Android开发中,SurfaceView是一种特殊的视图,它允许开发者在应用程序中创建高性能的...实践中,可以结合其他的动画库,如Android的Property Animation API,或者第三方库如NineOldAndroids,来进一步丰富动画效果。
在这个"Android进阶篇之引导页系列之强大的SurfaceView实现动画引导页(2)"中,我们将深入探讨如何利用SurfaceView来创建动态且引人入胜的引导页动画。 SurfaceView是Android系统提供的一种特殊视图,它允许开发者...
Android原生并不支持GIF格式,所以通常我们会选择第三方库,如 Glide、Picasso 或者 Android-Universal-Image-Loader 等,这些库都提供了加载和播放GIF的功能。在这里,我们将以一个常用的库,如 Glide 为例。 1. *...
SurfaceView创建了一个独立的显示表面,这个表面位于应用窗口之上,与应用程序主线程分离,从而可以在后台线程中进行渲染,提高性能。这对于处理视频流非常有利,因为视频解码和渲染可以在这个独立的线程中进行,...
在不使用任何第三方库的情况下,我们可以自定义一个布局管理器来处理页面的滑动和切换逻辑。 1. **布局设计**: - 可以使用`ViewPager`作为基础框架,`ViewPager`支持左右滑动切换页面,但不直接支持上下滑动。...
本篇文章主要探讨了在Android中使用SurfaceView和View两种不同的方法来处理摇摇棒事件,这是在2011年第二届Google暑期大学生博客分享大赛中的一个Android成长篇主题。我们将深入分析这两个组件在处理传感器数据和...
#### Android提高第二、三篇之SurfaceView SurfaceView是Android中用于实时渲染图形的组件,特别适用于处理视频或游戏等动态视觉内容。在提高篇中,SurfaceView被细分为上下两部分进行深入讲解,这反映了其复杂性和...
SurfaceView在Android开发中是一种特殊的View,主要用于处理高性能、低延迟的图形绘制,例如游戏、视频播放或像抽奖转盘这样的复杂动画。SurfaceView通过创建一个独立的Surface,并将其渲染到窗口上,允许UI更新与...
总结来说,利用Android的SurfaceView,结合基本的物理原理,我们可以创建出一个逼真的小球落下并弹起的动画。这是一个很好的起点,对于想要深入Android游戏开发的人来说,可以进一步扩展到更复杂的游戏机制,如多...
3. **叠加SurfaceView**:为了让顶层的SurfaceView(绘制图形的)覆盖底层的SurfaceView(摄像头预览),你可以使用`RelativeLayout`或`FrameLayout`作为父布局,并设置合适的层级关系。例如,通过设置`android:...
在实际项目中,可能会涉及到更复杂的场景,比如使用自定义的MediaExtractor或MediaCodec来处理解码,或者使用ijkplayer、ExoPlayer等第三方库来增强播放功能和兼容性。`tzt_mediavideo`这个文件可能包含了一些示例...