关于使用SurfaceView,网上很多版本都是直接创建一个SurfaceView的子类,然后实现

SurfaceHolder.Callback, Runnable接口,并启动一个线程。一来就搞这么一套东西,让人很不理解。

1,其实SurfaceView就是一个控件,我们完全可以直接在上面绘制图像。方法如下:

在布局文件中包含一个Surfaceview的组件:

如下:

<SurfaceView
         android:id="@+id/surface"
         android:layout_gravity="center"
         android:layout_width="match_parent"
         android:layout_height="match_parent" />

然后在代码中如下编码就可以了:

Canvas canvas = surfaceHolder.lockCanvas();
      if (null == canvas){
              return;
      }

      canvas.drawRect(rect, mpaint);
      surfaceHolder.unlockCanvasAndPost(canvas);

  2,但是这么写的话就没法利用surfaceView可以在子线程中绘制的这个优势,一般我们都是在UI主线程中更新控件的,但是SurfaceView允许在子线程中更新,这就是为什么很多文章中介绍surface使用时,直接启动一个子线程来搞的原因。

 

3,启动子线程来绘制,也有两种方法,一种是直接在要绘制的activity中实现SurfaceHolder.CallBack接口与Runnable接口;

如这边文章中的例子就是这种方式。

另外一种就是最常见的创建一个SurfacView的子类来作为自定义的控件。例子太多就不介绍了。

 

4,按照如上方式使用surfaceview之后,有点卡顿的感觉:

原因分析:

上面创建了一个线程,几乎是死循环,就算没有新视图的刷新,线程还是一直在运行,这样是对系统资源的一种浪费,那么该如何优化线程的使用呢?

加延时吗?

加延时的化,Android屏幕的刷新时间是16ms,如果超过这个时间,便会有卡顿的感觉,也就是说加延时的话最多在每次循环里加16ms.

每次延时16ms,在一般情况下有点杯水车薪的感觉,然后有时候也可能有频繁刷新的请求,在请求频繁时或者绘制强度比较高的情况下16ms依然是造成视图卡顿的.

那么到底应该如何优化线程的调用呢?
 

5,接下来看下如何解决使用SurfaceView后有时有卡顿现象的问题:使用HandlerThread代替普通的Thread。

     HandlerThread一个最主要的应用就是:每个几秒钟更新数据或图片。https://www.jianshu.com/p/a03ef2a0c026

     相比于普通的Thread,在没有任务请求时时阻塞挂起的,几乎不会消耗多少系统资源,有任务请求时又可以快速唤醒运行,相比于使用直接使用Thread明显更合理不少。