SurfaceView & TextureView 小记

来源

Android中提供了View进行绘图处理,View可以满足大部分的绘图需求,但是有时候,View却显得力不从心,所以Android提供了SurfaceView给Android开发者,以满足更多的绘图需求。下面就让我们一起来了解一下SurfaceView。

View和SurfaceView的区别

1 . View适用于主动更新的情况,而SurfaceView则适用于被动更新的情况,比如频繁刷新界面。

2 . View在主线程中对页面进行刷新,而SurfaceView则开启一个子线程来对页面进行刷新。

3 . View在绘图时没有实现双缓冲机制,SurfaceView在底层机制中就实现了双缓冲机制。

为什么使用SurfaceView?通俗来讲

  1. 如果屏幕刷新频繁,onDraw方法会被频繁的调用,onDraw方法执行的时间过长,会导致掉帧,出现页面卡顿。而SurfaceView采用了双缓冲技术,提高了绘制的速度,可以缓解这一现象。
  2. view的onDraw方法是运行在主线程中的,会轻微阻塞主线程,对于需要频繁刷新页面的场景,而且onDraw方法中执行的操作比较耗时,会导致主线程阻塞,用户事件的响应受到影响,也就是响应速度下降,影响了用户的体验。而SurfaceView可以在自线程中更新UI,不会阻塞主线程,提高了响应速度。

双缓冲技术

双缓冲技术是游戏开发中的一个重要的技术。当一个动画争先显示时,程序又在改变它,前面还没有显示完,程序又请求重新绘制,这样屏幕就会不停地闪烁。

双缓冲技术是把要处理的图片在内存中处理好之后,再将其显示在屏幕上。

双缓冲主要是为了解决 反复局部刷屏带来的闪烁。把要画的东西先画到一个内存区域里,然后整体的一次性画出来。

SurfaceView用法

  1. 通过lockCanvas()方法获得Canvas对象

  2. 在子线程中使用Canvas对象进行绘制

  3. 使用unlockCanvasAndPost()方法将画布内容进行提交

注意: lockCanvas() 方法获得的Canvas对象仍然是上次绘制的对象,由于我们是不断进行绘制,但是每次得到的Canvas对象都是第一次创建的Canvas对象。

public class SurfaceViewTemplate extends SurfaceView implements SurfaceHolder.Callback, Runnable {
    
    private SurfaceHolder mSurfaceHolder;
    //绘图的Canvas
    private Canvas mCanvas;
    //子线程标志位
    private boolean mIsDrawing;
    
    public SurfaceViewTemplate(Context context) {
        this(context, null);
    }

    public SurfaceViewTemplate(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public SurfaceViewTemplate(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        initView();
    }

    @Override
    public void surfaceCreated(SurfaceHolder holder) {
        mIsDrawing = true;
        //开启子线程
        new Thread(this).start();
    }

    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {

    }

    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {
        mIsDrawing = false;
    }

    @Override
    public void run() {
        while (mIsDrawing){
            drawSomething();
        }
    }
    //绘图逻辑
    private void drawSomething() {
        try {
            //获得canvas对象
            mCanvas = mSurfaceHolder.lockCanvas();
            //绘制背景
            mCanvas.drawColor(Color.WHITE);
            //绘图
        }catch (Exception e){

        }finally {
            if (mCanvas != null){
                //释放canvas对象并提交画布
                mSurfaceHolder.unlockCanvasAndPost(mCanvas);
            }
        }
    }

    /**
     * 初始化View
     */
    private void initView(){
        mSurfaceHolder = getHolder();
        mSurfaceHolder.addCallback(this);
        setFocusable(true);
        setKeepScreenOn(true);
        setFocusableInTouchMode(true);
    }
}

TextureView与SurfaceView区别

TextureView和SurfaceView都是继承自View类的,但是与其它View不同的是,两者都能在独立的线程中绘制和渲染,在专用的GPU线程中大大提高渲染的性能。子线程更新UI,也是相交于普通View的优势所在。

  • SurfaceView
    专门提供了嵌入视图层级的绘制界面,开发者可以控制该界面像Size等的形式,能保证界面在屏幕上的正确位置。

    局限:

    1. 由于是独立的一层View,更像是独立的一个Window,不能加上动画、平移、缩放
    2. 两个SurfaceView不能相互覆盖。
  • TextureView
    更像是一般的View,像TextView那样能被缩放、平移,也能加上动画。
    局限:

    1. 只能在开启了硬件加速的Window中使用,并且消费的内存要比SurfaceView多,并伴随着1-3帧的延迟。
    2. TextureView在Andriod4.0之后的API中才能使用
  • 子线程UI更新方法

方法
SurfaceView SurfaceHolder.addCallback
TextureView TextureView.setSurfaceTextureListener
  • 画面更新方式
    • SurfaceView:双缓冲功能使画面更加流畅,但是由于其holder的存在导致画面更新会存在间隔。同时也不能进行像View一样的setAlpha和setRotation方法,但是对于需要不断告诉更新画布的应用是极好的选择。
    • TextureView:更加适合视频播放器或相机应用的开发

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容