Android视图框架对于创建复杂布局非常方便。然而,这种便利是以性能为代价的。当性能至关重要的时候,Android提供了几种更强大的图形处理能力,当然难度也是随之上升了。在本节中,我将介绍:
(1)SurfaceView和TextureView类如何使用标准的Canvas对象并与单独的渲染进程结
合,得到比标准视图更好的性能;
(2)新得RenderScript框架可以被用于创建独立结构的图形渲染;
(3)OpenGL可用于一些严格的图形工作和游戏。
1、SurfaceView和TextureView类如何使用标准的Canvas对象并与单独的渲染进程结
合,得到比标准视图更好的性能;
与普通视图不同,所有在SurfaceView上的绘图都发生在一个独立的线程上。要想在SurfaceView上绘图,你必须调用SurfaceHolder的lockCanvas方法,这将返回一个Canvas对象。lockCanvas方法阻止SurfaceView更新底层界面(阻止它删除你先前画的),直到你调用响应的unlockCanvasAndPost方法为止。这消除了对界面改变同步的需求(尽管你仍然需要在进程之间同步一些字段)。你应该把对SurfaceView所有的绘制包装进lockCanvas和unlockCanvasAndPost模块中。下面我提供了两种绘制SurfaceView的方法,主要来演示lockCanvas的重要作用:
1.1 创建自己的工程,将contentView设置为自己的类(继承surfaceView)
public class MainActivity extends Activity{ private static final String TAG = "MainActivity"; private int Y_center,X_center; //Y轴的一半 private int X_width; //X轴的点数 private int Y_point[];//曲线所需要的Y轴点数 @Override protected void onCreate(Bundle savedInstanceState){ super.onCreate(savedInstanceState); setContentView(new exampleSurfaceView(this)); }
这里我已经将下面将要使用的变量列出,setContentView(new exampleSurfaceView(this)); 接下来我们要定义自己的新类了,继承surfaceView,这里不再使用视图了。
1.2 编写自己的exampleSurfaceView类继承surfaceView
public class exampleSurfaceView extends SurfaceView implements SurfaceHolder.Callback{ DrawingThread mThread; private SurfaceHolder holder; /******************************************************************************** * 获得holder对象,实例化mThread,计算屏幕大小取出Y轴的中心高度 * * @param context */ public exampleSurfaceView(Context context){ super(context); holder = getHolder(); holder.addCallback(this); mThread = new DrawingThread(holder); DisplayMetrics dm = new DisplayMetrics(); getWindowManager().getDefaultDisplay().getMetrics(dm); Y_center = dm.heightPixels/2; X_width = dm.widthPixels; X_center = X_width/2; Log.i(TAG, "屏幕的一半高度为:"+Y_center+"屏幕的一半宽度为:"+X_center); Y_point = new int[X_width]; for(int i=0; i<Y_point.length; i++){ Y_point[i] = Y_center-(int) (100 * Math.sin(i * 2 * Math.PI / 180)); } } //创建三角形 @Override public void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2, int arg3) { // TODO Auto-generated method stub Log.i(TAG, "this is changeed format:"+arg1+"width:"+arg2+"height:"+arg3); } //更新surface,并起动 @Override public void surfaceCreated(SurfaceHolder holder) { // TODO Auto-generated method stub mThread.keepRunning = true; mThread.start(); } //终止线程,回收空间 @Override public void surfaceDestroyed(SurfaceHolder holder) { // TODO Auto-generated method stub mThread.keepRunning = false; boolean retry=true; while(retry){ try{ mThread.join(); retry = false; }catch(InterruptedException e){ e.printStackTrace(); } } } }
这里我们在surfaceView创建的时候开启线程,在surfaceView销毁的时候,回收线程,最后我们在把线程内容给出。
1.3 通过线程实现绘制图形。
public class DrawingThread extends Thread { boolean keepRunning=true; private SurfaceHolder holder; public DrawingThread(SurfaceHolder holder) { // TODO Auto-generated constructor stub this.holder =holder; } @Override public void run(){ Canvas c; int count = 0; int X_old,Y_old,X_new,Y_new; X_old = 0; Y_old = Y_point[X_old]; while(keepRunning){ c = null; try{ synchronized(holder){//synchronized锁的永远是对象,获得holder对象 c = holder.lockCanvas(); c.drawColor(Color.BLACK); Paint mPaint = new Paint(); //创建画笔 mPaint.setStrokeWidth(5); mPaint.setColor(Color.RED); X_new = X_old+1; Y_new = Y_point[X_new]; c.drawLine(X_old, Y_old, X_new, Y_new, mPaint); c.drawText("这是第"+(count++)+"秒", X_center, Y_center, mPaint); X_old++; Y_old = Y_point[X_old]; if(X_old == X_width-1){ Log.i(TAG, "game over"); X_old = 1; Y_old = Y_point[X_old]; } Thread.sleep(10); } }catch(Exception e){ e.printStackTrace(); }finally{ if(c != null){ holder.unlockCanvasAndPost(c); } } } } }
这两个图是上面程序绘制的,不断的调用c.drawColor(Color.BLACK);来清除图层
不使用c.drawColor(Color.BLACK);
我这里是线程多次执行,绘制出来的,当然也可一在线程执行一次的时候直接绘制完毕,这里可以自己微微改动。