SurfaceView与多线程的混搭

来源:互联网 发布:暗影格斗2mac版存档 编辑:程序博客网 时间:2024/04/25 18:02

转自http://blog.csdn.net/hellogv/article/details/5986835

SurfaceView与多线程混搭,是为了防止动画闪烁而实现的一种多线程应用技术。android的多线程用法与Java的多线程用法完全一样,本文不做多线程方面的介绍了。直接讲解SurfaceView与多线程的混合使用,即开一条线程专门读取图片,另外一条线程专门绘图。

先看效果图,左边是开单个线程读取并绘图,右边是开两个线程,一个专门读取图片,一个专门绘图:

开启双线程

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

main.xml的源码:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<?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">
    <LinearLayout
        android:id="@+id/LinearLayout01"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content">
        <Button
            android:id="@+id/Button01"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="单个独立线程"
            />
        <Button
            android:id="@+id/Button02"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="两个独立线程"
            />
    </LinearLayout>
    <SurfaceView
        android:id="@+id/SurfaceView01"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"></SurfaceView>
</LinearLayout>

本文程序的源码:

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

原创粉丝点击