转载请注明出处:王亟亟的大牛之路

近期两天都没有写文章,一方面是自己在看书。一方面不知道写什么,本来昨天想写Glide或者RxAndroid的东西结果公司的“狗屎”网怎么都刷不好Gradle我也是无语了(翻墙也没用)。准备今天背着笔记本 回家搞。真是服了。。


抱怨的话不说了,来看下这一篇要讲的主角 SurfaceView,关于SurfaceView的文章事实上在别的一些网站上也有,由于我之前没写过,所以也就一直没整这部分的内容(别人写的好坏反正找好的点自己吸收吧,嘿嘿)

问题:SurfaceView是什么?

View类的子类

public class SurfaceView extends View

surfaceView是在一个新起的单独线程中能够又一次绘制画面而View必须在UI的主线程中更新画面。

这点非常重要。那我们能够在哪使用它?那些一直在刷的。还会耗性能的一些UI内容我们能够让他去画。毕竟不在主线程(想想渐变这类的东西)

再例举一些使用场景。假设我要画一个视图他和用户有交互。那么用View还是SurfaceView?

像这种情况就比較推荐用View由于要有Touch事件,用View更合适。而0交互的那些场景用用SurfaceView对性能会有一定的帮助,接下来用样例来详细描写叙述怎样用SurfaceView。


先上效果图

效果非常easy就是在一个Activity里设置了个白色背景,然后写了个“你好”。

来看下代码(一些知识点在标注里说明)

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View; /**
* Created by jiajiewang on 16/3/22.
*/ public class CustomView extends SurfaceView implements SurfaceHolder.Callback, View.OnTouchListener {
private Context context;
private SurfaceHolder surfaceHolder;
private CustomThread customThread; public CustomView(Context context, AttributeSet attrs) {
super(context, attrs);
this.setKeepScreenOn(true);
this.setFocusable(true);
//用于触摸事件
this.setLongClickable(true);
this.context = context;
//获取对象实例
surfaceHolder = this.getHolder();
// 给SurfaceView加入回调
surfaceHolder.addCallback(this);
//创建工作线程
customThread = new CustomThread(surfaceHolder); } //创建的时候调用
@Override
public void surfaceCreated(SurfaceHolder holder) {
customThread.canRun = true;
//工作线程開始工作
customThread.start();
Log.d("-->surfaceCreated", "surfaceCreated");
} //发生改变的时候调用
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { Log.d("-->surfaceChanged", "surfaceChanged");
} //销毁时的时候调用
@Override
public void surfaceDestroyed(SurfaceHolder holder) { customThread.canRun = false;
Log.d("-->surfaceDestroyed", "surfaceDestroyed"); } @Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) { case MotionEvent.ACTION_DOWN: Log.d("MotionEvent", "ACTION_DOWN"); break; case MotionEvent.ACTION_UP: Log.d("MotionEvent", "ACTION_UP"); break; case MotionEvent.ACTION_MOVE: Log.d("MotionEvent", "ACTION_MOVE"); break; } return super.onTouchEvent(event); }
} //工作线程
class CustomThread extends Thread {
private SurfaceHolder surfaceHolder;
public boolean canRun; public CustomThread(SurfaceHolder surfaceHolder) {
this.surfaceHolder = surfaceHolder;
canRun = true;
} @Override
public void run() { while (canRun) {
Canvas canvas = null;
//线程同步
synchronized (surfaceHolder) {
//创建画笔
Paint paint = new Paint();
paint.setColor(Color.GREEN);
paint.setTextSize(200);
// 锁定画布(想一下,相似Bitmap的效果)
canvas = surfaceHolder.lockCanvas();
//画背景
canvas.drawColor(Color.WHITE);
//画字
canvas.drawText("妈蛋", 100, 300, paint);
} if (canvas != null) {
// 结束锁定
surfaceHolder.unlockCanvasAndPost(canvas);
} } }

流程:

这是一个自己定义的SurfaceView并实现了SurfaceHolder.Callback

在这个自己定义SurfaceView被创建的时候去开启工作线程去做了该做的事。MainActivity没做不论什么事也就是 载入一下,还是在XML里引入的。

  <sample.wjj.surfaceviewdemo.CustomView
android:layout_width="wrap_content"
android:layout_height="wrap_content" />

那我们来看下 SurfaceView一些比較重要的(经常使用的)方法。

getHolder() 获取SurfaceHolder对象,Surface 就在SurfaceHolder对象内

Canvas lockCanvas()或则Canvas lockCanvas(Rect dirty) 获取Canvas对象

unlockCanvasAndPost(Canvas canvas) 函数会释放该锁,用于操作UI

在调用lockCanvas函数获取Canvas后,SurfaceView会获取Surface的一个同步锁直到调用unlockCanvasAndPost(Canvas canvas)函数才释放该锁,这里的同步机制保证在Surface绘制过程中不会被改变(被摧毁、改动)。

再说一下绘制的类型(更好的运用性能)

SURFACE_TYPE_NORMAL:用RAM缓存原生数据的普通Surface 

SURFACE_TYPE_HARDWARE:适用于DMA(Direct memory access )引擎和硬件加速的Surface 

SURFACE_TYPE_GPU:适用于GPU加速的Surface 

SURFACE_TYPE_PUSH_BUFFERS:表明该Surface不包括原生数据,Surface用到的数据由其它对象提供。在Camera图像预览中就使用该类型的Surface,有Camera负责提供给预览Surface数据。这样图像预览会比較流畅。

假设设置这种类型则就不能调用lockCanvas来获取Canvas对象了。

由于没有什么其它第三方资源所以就不存源代码了。

假设在学习的过程中有什么问题或者项目中有什么问题须要找人探讨的能够扫下面微信和我沟通(私人微信都不是什么平台的会相对回的比較快,骚扰的别来,坏人烂JJ!!)

能够在子线程绘画的View SurfaceView的更多相关文章

  1. Android中不能在子线程中更新View视图的原因

    这是一条规律,很多coder知道,但原因是什么呢? 如下: When a process is created for your application, its main thread is ded ...

  2. Android多线程之(一)View.post()源码分析——在子线程中更新UI

    提起View.post(),相信不少童鞋一点都不陌生,它用得最多的有两个功能,使用简便而且实用: 1)在子线程中更新UI.从子线程中切换到主线程更新UI,不需要额外new一个Handler实例来实现. ...

  3. android 不能在子线程中更新ui的讨论和分析

    问题描写叙述 做过android开发基本都遇见过 ViewRootImpl$CalledFromWrongThreadException,上网一查,得到结果基本都是仅仅能在主线程中更改 ui.子线程要 ...

  4. Android在子线程中更新UI(二)

    MainActivity如下: package cc.testui2; import android.os.Bundle; import android.view.View; import andro ...

  5. OkHttp3几个简单的例子和在子线程更新UI线程的方法

    okHttp用于android的http请求.据说很厉害,我们来一起尝尝鲜.但是使用okHttp也会有一些小坑,后面会讲到如何掉进坑里并爬出来. 首先需要了解一点,这里说的UI线程和主线程是一回事儿. ...

  6. 子线程调用invalidate()产生“Only the original thread that created a view hierarchy can touch its views.”原因分析

    目录 1.异常出处 2.从View.invalidate()方法开始分析 3.ViewRootImpl如何与View进行关联:从Activity的setContentView开始分析 3.1 最顶层的 ...

  7. Android可以子线程更新UI?

    初了解Android的时候,就知道Android是不能在子线程更新UI的,不然程序会直接抛出异常,告诉你,别给我在自线程搞事情! 但是,这个是针对普通的view做的限制,而TextureView,Su ...

  8. Android之View / SurfaceView / GLSurfaceView

    Android游戏当中主要的除了控制类外就是显示类View.SurfaceView是从View基类中派生出来的显示类.android游戏开发中常用的三种视图是:view.SurfaceView和GLS ...

  9. android: View, SurfaceView, GLSurfaceView, TextureView 区别与联系

    区别与联系 View: 显示视图,内置画布,提供了图形绘制函数.触屏事件.按键事件函数等,必须在UI主线程内更新画面,速度较慢: SurfaceView: 基于view视图进行拓展的视图类,更适合2D ...

随机推荐

  1. spring整合redis客户端及缓存接口设计

    一.写在前面 缓存作为系统性能优化的一大杀手锏,几乎在每个系统或多或少的用到缓存.有的使用本地内存作为缓存,有的使用本地硬盘作为缓存,有的使用缓存服务器.但是无论使用哪种缓存,接口中的方法都是差不多. ...

  2. Java数据类型转换1

    1 如何将字串 String 转换成整数 int? A. 有两个方法: 1). int i = Integer.parseInt([String]); 或 i = Integer.parseInt([ ...

  3. mysqlslap: Error when connecting to server: 2001 Can't create UNIX socket (24) 解决方法

    在用mysqlslap对mysql进行压力测试遇到mysqlslap: Error when connecting to server: 2001 Can't create UNIX socket ( ...

  4. 【Oracle】DG中物理备库、快照备库的相互转换

    一.物理备库切换快照备库 1. 如果正在运行日志应用,先停止 ALTER DATABASE RECOVER MANAGED STANDBY DATABASE CANCEL; 2. 确保数据库为MOUN ...

  5. JQuery特效之心形图片墙

    效果如图: 代码如下: <!doctype html> <html lang="en"> <head> <meta charset=&qu ...

  6. 新书《计算机图形学基础(OpenGL版)》PPT已发布

    为方便有些老师提前备课,1-10章所有章节已发布到本博客中. 欢迎大家下载使用,也欢迎大家给我们的新书反馈与意见,谢谢!

  7. 怎么在阿里云搭建一个WordPress博客(超详细教程)

    想以正确的方式启动一个 WordPress 博客吗?我知道,这可能是一个令人恐惧的想法 -- 其实你并不孤单.但是,在帮助很多用户创建博客之后,我决定编写一份详细的指南,让任何没有技术知识的人都能拥有 ...

  8. Node.js常用express方法

    Node.js 手册查询-Express 方法 1.send方法 send 方法向浏览器发送一个响应信息,并可以智能处理不同类型的数据 send方法在输出响应时会自动进行一些设置,比如HEAD信息.H ...

  9. 关于如何利用js判断IE浏览器各种版本问题

    <!--[if IE 6]> IE 浏览器版本 6 <![endif]-->   <!--[if IE 7]> IE 浏览器版本 7 <![endif]--& ...

  10. BZOJ 3514 GERALD07加强版 (LCT+主席树)

    题目大意:给定n个点m条边无向图,每次询问求当图中有编号为[L,R]的边时,整个图的联通块个数,强制在线 神题!(发现好久以前的题解没有写完诶) 我们要求图中联通块的个数,似乎不可搞啊. 联通块个数= ...