Android SurfaceView双缓冲

it2022-05-05  99

原文转于:http://www.oschina.net/code/snippet_54100_1422

双缓冲是为了防止动画闪烁而实现的一种多线程应用,基于SurfaceView的双缓冲实现很简单,开一条线程并在其中绘图即可。本文介绍基于SurfaceView的双缓冲实现,以及介绍类似的更高效的实现方法。 本文程序运行截图如下,左边是开单个线程读取并绘图,右边是开两个线程,一个专门读取图片,一个专门绘图: 对比一下,右边动画的帧速明显比左边的快,左右两者都没使用Thread.sleep()。为什么要开两个线程一个读一个画,而不去开两个线程像左边那样都 “边读边画”呢?因为SurfaceView每次绘图都会锁定Canvas,也就是说同一片区域这次没画完下次就不能画,因此要提高双缓冲的效率,就得开一条线程专门画图,开另外一条线程做预处理的工作。   标签: SurfaceView 双缓冲 Android SDK  

代码片段(3)

[图片] 程序运行截图

[代码] main.xml

view source print ? 01<?xml version="1.0" encoding="utf-8"?> 02<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 03    android:layout_width="fill_parent" android:layout_height="fill_parent" 04    android:orientation="vertical"> 05   06    <LinearLayout android:id="@+id/LinearLayout01" 07        android:layout_width="wrap_content" android:layout_height="wrap_content"> 08        <Button android:id="@+id/Button01" android:layout_width="wrap_content" 09            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>

[代码] TestSurfaceView.java

view source print ? 001package com.testSurfaceView; 002   003import java.lang.reflect.Field; 004import java.util.ArrayList; 005import android.app.Activity; 006import android.graphics.Bitmap; 007import android.graphics.BitmapFactory; 008import android.graphics.Canvas; 009import android.graphics.Paint; 010import android.graphics.Rect; 011import android.os.Bundle; 012import android.util.Log; 013import android.view.SurfaceHolder; 014import android.view.SurfaceView; 015import android.view.View; 016import android.widget.Button; 017   018public class TestSurfaceView extends Activity { 019    /** Called when the activity is first created. */ 020    Button btnSingleThread, btnDoubleThread; 021    SurfaceView sfv; 022    SurfaceHolder sfh; 023    ArrayList<Integer> imgList = new ArrayList<Integer>(); 024    int imgWidth, imgHeight; 025    Bitmap bitmap;//独立线程读取,独立线程绘图 026   027    @Override 028    public void onCreate(Bundle savedInstanceState) { 029        super.onCreate(savedInstanceState); 030        setContentView(R.layout.main); 031   032        btnSingleThread = (Button) this.findViewById(R.id.Button01); 033        btnDoubleThread = (Button) this.findViewById(R.id.Button02); 034        btnSingleThread.setOnClickListener(new ClickEvent()); 035        btnDoubleThread.setOnClickListener(new ClickEvent()); 036        sfv = (SurfaceView) this.findViewById(R.id.SurfaceView01); 037        sfh = sfv.getHolder(); 038        sfh.addCallback(new MyCallBack());// 自动运行surfaceCreated以及surfaceChanged 039    } 040   041    class ClickEvent implements View.OnClickListener { 042   043        @Override 044        public void onClick(View v) { 045   046            if (v == btnSingleThread) { 047                new Load_DrawImage(0, 0).start();//开一条线程读取并绘图 048            } else if (v == btnDoubleThread) { 049                new LoadImage().start();//开一条线程读取 050                new DrawImage(imgWidth + 10, 0).start();//开一条线程绘图 051            } 052   053        } 054   055    } 056   057    class MyCallBack implements SurfaceHolder.Callback { 058   059        @Override 060        public void surfaceChanged(SurfaceHolder holder, int format, int width, 061                int height) { 062            Log.i("Surface:", "Change"); 063   064        } 065   066        @Override 067        public void surfaceCreated(SurfaceHolder holder) { 068            Log.i("Surface:", "Create"); 069   070            // 用反射机制来获取资源中的图片ID和尺寸 071            Field[] fields = R.drawable.class.getDeclaredFields(); 072            for (Field field : fields) { 073                if (!"icon".equals(field.getName()))// 除了icon之外的图片 074                { 075                    int index = 0; 076                    try { 077                        index = field.getInt(R.drawable.class); 078                    } catch (IllegalArgumentException e) { 079                        // TODO Auto-generated catch block 080                        e.printStackTrace(); 081                    } catch (IllegalAccessException e) { 082                        // TODO Auto-generated catch block 083                        e.printStackTrace(); 084                    } 085                    // 保存图片ID 086                    imgList.add(index); 087                } 088            } 089            // 取得图像大小 090            Bitmap bmImg = BitmapFactory.decodeResource(getResources(), 091                    imgList.get(0)); 092            imgWidth = bmImg.getWidth(); 093            imgHeight = bmImg.getHeight(); 094        } 095   096        @Override 097        public void surfaceDestroyed(SurfaceHolder holder) { 098            Log.i("Surface:", "Destroy"); 099   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    }; 173}

转载于:https://www.cnblogs.com/lslzmx/archive/2012/01/10/2317936.html

相关资源:DirectX修复工具V4.0增强版

最新回复(0)