android surfaceview 多线程,主线程之外的线程中向屏幕绘图 - SurfaceView

在一般情况下,应用程序的View都是在相同的GUI线程中绘制的。这个主应用程序线程同时也用来处理所有的用户交互(例如按钮单击或者文本输入)。

对于一个View的onDraw()方法,不能够满足将其移动到后台线程中去。因为从后台线程修改一个GUI元素会被显式地禁止的。而SurfaceView,可以在主线程之外的线程中向屏幕绘图。这样可以避免画图任务繁重的时候造成主线程阻塞,从而提高了程序的反应速度。

当需要快速,主动地更新View的UI,或者当前渲染代码阻塞GUI线程的时间过长的时候,SurfaceView就是解决上述问题的最佳选择。比如一个人在一直跑动。这就需要一个单独的thread不停的重绘人的状态,避免阻塞main

UI thread。所以显然view不合适,需要surfaceView来控制。

被动更新画面的。比如棋类,这种用view就好了。因为画面的更新是依赖于onTouch 来更新,可以直接使用

invalidate。因为这种情况下,这一次Touch和下一次的Touch需要的时间比较长些,不会产生影响。

SurfaceView使用的方式与任何View所派生的类都是完全相同的。可以像其他View那样应用动画,并把它们放到布局中。

SurfaceView 有一个原则,所有的绘图工作必须得在Surface

被创建之后才能开始。可以被直接复制到显存从而显示出来,这使得显示速度会非常快,而在Surface

被销毁之前必须结束。所以Callback 中的surfaceCreated 和surfaceDestroyed

就成了绘图处理代码的边界。

需要重写的方法

(1)public void surfaceChanged(SurfaceHolder

holder,int format,int width,int height){}

//在surface的大小发生改变时激发

(2)public void surfaceCreated(SurfaceHolder

holder){}

//在创建时激发,一般在这里调用画图的线程。

(3)public void surfaceDestroyed(SurfaceHolder

holder) {}

//销毁时激发,一般在这里将画图的线程停止、释放。

一个典型的SurfaceView

设计模型包括一个由Thread所派生的类,它可以在创建的时候接收对当前的SurfaceHolder的引用,在Thread的run方法中,可以由该引用可以得到布局中SurfaceView的canvas,

并更新它。

package dhb.test;

import android.app.Activity;

import android.content.Context;

import android.graphics.Canvas;

import android.graphics.Color;

import android.graphics.Paint;

import android.graphics.Rect;

import android.os.Bundle;

import android.view.SurfaceHolder;

import android.view.SurfaceView;

public class MysurfaceTestActivity extends Activity {

int count =

0; @Override

public void

onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(new MyView(this));

}

public

void doDraw(Canvas c){

c.drawColor(Color.BLACK);//设置画布背景颜色

Paint p = new Paint(); //创建画笔

p.setColor(Color.WHITE);

Rect r = new Rect(100, 50, 300, 250);

c.drawRect(r, p);

c.drawText("这是第"+(count)+"秒", 100, 310, p);

}

//视图内部类

class

MyView extends SurfaceView implements SurfaceHolder.Callback

{

private SurfaceHolder holder;

private MyThread myThread;

private MyDrawThread myDrawThread;

public MyView(Context context) {

super(context);

// TODO Auto-generated constructor stub

holder = this.getHolder();

holder.addCallback(this);

myThread = new MyThread (); //创建一个数据更新线程

myDrawThread = new MyDrawThread (holder);//创建一个绘图线程

}

@Override

public void surfaceChanged(SurfaceHolder holder, int format, int

width,

int height) {

// TODO Auto-generated method stub

System.out.println("surfaceChanged");

}

@Override

public void surfaceCreated(SurfaceHolder holder) {

// TODO Auto-generated method stub

System.out.println("surfaceCreated");

myDrawThread.isRun = true;

myDrawThread.start();

myThread.isRun = true;

myThread.start();

}

@Override

public void surfaceDestroyed(SurfaceHolder holder) {

// TODO Auto-generated method stub

myDrawThread.isRun = false;

myThread.isRun = false;

System.out.println("surfaceDestroyed");

}

}

//线程内部类

//数据更新线程

class

MyThread extends Thread

{

public boolean isRun;

public MyThread ()

{

isRun = true;

}

@Override

public void run()

{

System.out.println("MyThread - run");

while(isRun)

{

count++;

try

{

Thread.sleep(1000);

}

catch (InterruptedException e)

{

//

TODO Auto-generated catch block

e.printStackTrace();

}

}

}

}

//创建一个绘图线程

class

MyDrawThread extends Thread

{

private SurfaceHolder holder;

public boolean isRun ;

public MyDrawThread(SurfaceHolder holder)

{

this.holder =holder;

isRun = true;

}

@Override

public void run()

{

System.out.println("MyDrawThread - run");

while(isRun)

{

Canvas c = null;

try

{

synchronized (holder)

{

c =

holder.lockCanvas();//锁定画布,一般在锁定后就可以通过其返回的画布对象Canvas,在其上面画图等操作了。

doDraw(c);

Thread.sleep(1000);//睡眠时间为1秒

}

}

catch (Exception e) {

// TODO: handle exception

e.printStackTrace();

}

finally

{

if(c!= null)

{

holder.unlockCanvasAndPost(c);//结束锁定画图,并提交改变。

}

}

}

}

} }

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值