之前做下载程序的时候没有注意过效率,在这个靠硬件来拉开用户体验的时代应用程序内算法效率很容易被忽视。
以前的思路是用 inputstream 来down数据,存到 byte[] 中直接写到文件中。
后来重温编程之美的时候看到了类似的文章。如果要提高下载效率,需要把写文件和读文件分开,一个线程负责读数据,另一个线程负责写数据,数据池一定要用线程安全的数据结构。
***********************************************我是下载和Surfaceview的分割线***************************************************
在用SurfaceView做动画的时候也是同样的道理,如果读出一张Bitmap再去显示,界面肯定会卡。
需要使用双缓冲,开辟两个线程,一个用来读图,一个用来显示。
下面是示例代码:
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 }; 173 }