Android_SurfaceView_绘图覆盖刷新及脏矩形刷新方法
android surface用法 -回复

android surface用法-回复Android Surface用法详解Android Surface,即安卓表面,是Android平台中重要的图形处理组件之一。
它提供了一个用于绘制2D图形的画布,同时也允许其他线程对其进行修改。
在本文中,我们将一步一步地介绍Android Surface的用法,帮助读者更好地理解和使用这个重要的组件。
第一步:创建SurfaceView在使用Android Surface之前,我们首先需要在布局文件中添加一个SurfaceView。
SurfaceView是一个可以直接与Surface进行交互的视图组件。
我们可以使用如下的XML代码在布局文件中创建一个SurfaceView:XML<SurfaceViewandroid:id="@+id/surfaceView"android:layout_width="match_parent"android:layout_height="match_parent" />同时,我们还需要在Java代码中找到布局文件中的SurfaceView,并对其进行初始化。
可以使用如下的代码获取SurfaceView的实例:JavaSurfaceView surfaceView = findViewById(R.id.surfaceView);第二步:获取SurfaceHolder对象接下来,我们需要获取SurfaceHolder对象。
SurfaceHolder是与SurfaceView绑定的对象,它可以用于管理SurfaceView的生命周期,以及对其进行操作。
我们可以通过调用SurfaceView的getHolder()方法来获取SurfaceHolder对象:JavaSurfaceHolder surfaceHolder = surfaceView.getHolder();第三步:设置SurfaceHolder的回调方法SurfaceHolder提供了一些回调方法,使我们能够在Surface发生变化时得到通知,进而对其进行操作。
android textureview绘制原理 -回复

android textureview绘制原理-回复Android TextureView 绘制原理TextureView 是Android 提供的一种用于在UI 界面中展示视频、图像等图形内容的View。
与常用的SurfaceView 不同,TextureView 可以直接嵌入到布局层级中,可以通过常规的LayoutParams 设置位置和大小,并且可以与其他View 进行动画和过渡效果。
本文将一步一步地解析TextureView 的绘制原理。
1. TextureView 简介TextureView 是View 的子类,它通过OpenGL ES 2.0 来渲染图像。
GLSurfaceView 也是使用OpenGL ES 2.0,但它封装了一些渲染相关的细节,使用起来更加简单。
而TextureView 则提供了更灵活的使用方式,但需要手动管理GLSurfaceView 内部的渲染流程。
2. TextureView 创建和初始化当TextureView 首次被添加到布局层级中时,会触发以下过程:- measure():系统调用measure() 方法测量TextureView 的尺寸。
此时TextureView 的尺寸为默认值0。
- onMeasure():在TextureView 的onMeasure() 方法中,根据测量模式和父容器的限制,计算出TextureView 的最终尺寸。
3. TextureView 的绘制流程TextureView 的绘制流程相对复杂。
以下是TextureView 的绘制流程的大致步骤:- onDraw():在onDraw() 方法中,将渲染请求发送到渲染线程。
- onAttachedToWindow():当TextureView 附加到窗口时,会创建一个新的渲染线程。
- onSurfaceTextureAvailable():在渲染线程中,通过SurfaceTexture 的onSurfaceTextureAvailable() 方法,创建一个新的EGLContext 和EGLSurface。
Android视图SurfaceView的实现原理分析

Android视图SurfaceView的实现原理分析在Android系统中,有一种特殊的视图,称为SurfaceView,它拥有独立的绘图表面,即它不与其宿主窗口共享同一个绘图表面。
由于拥有独立的绘图表面,因此SurfaceView的UI 就可以在一个独立的线程中进行绘制。
又由于不会占用主线程资源,SurfaceView一方面可以实现复杂而高效的UI,另一方面又不会导致用户输入得不到及时响应。
在本文中,我们就详细分析SurfaceView的实现原理。
在前面一文中提到,普通的Android控件,例如TextView、Button和CheckBox等,它们都是将自己的UI绘制在宿主窗口的绘图表面之上,这意味着它们的UI是在应用程序的主线程中进行绘制的。
由于应用程序的主线程除了要绘制UI之外,还需要及时地响应用户输入,否则的话,系统就会认为应用程序没有响应了,因此就会弹出一个ANR对话框出来。
对于一些游戏画面,或者摄像头预览、视频播放来说,它们的UI都比较复杂,而且要求能够进行高效的绘制,因此,它们的UI就不适合在应用程序的主线程中进行绘制。
这时候就必须要给那些需要复杂而高效UI的视图生成一个独立的绘图表面,以及使用一个独立的线程来绘制这些视图的UI。
在前面和这两个系统的文章中,我们主要分析了Android应用程序窗口是如何通过SurfaceFlinger服务来绘制自己的UI的。
一般来说,每一个窗口在SurfaceFlinger服务中都对应有一个Layer,用来描述它的绘图表面。
对于那些具有SurfaceView的窗口来说,每一个SurfaceView在SurfaceFlinger服务中还对应有一个独立的Layer或者LayerBuffer,用来单独描述它的绘图表面,以区别于它的宿主窗口的绘图表面。
无论是LayerBuffer,还是Layer,它们都是以LayerBase为基类的,也就是说,SurfaceFlinger服务把所有的LayerBuffer和Layer都抽象为LayerBase,因此就可以用统一的流程来绘制和合成它们的UI。
surfacetexture 方法

surfacetexture 方法SurfaceTe某ture是Android中用于处理实时图像流的一种类,它是从相机传感器到GPU纹理之间的中间层。
在SurfaceTe某ture中,图像从相机传感器获得,并从相机预览中产生纹理输出。
然后,可以将此纹理用于实时图像处理,如图像滤镜、特效等。
SurfaceTe某ture类具有许多有用的方法和功能,以下是其中一些重要的方法:1. SurfaceTe某ture构造函数:SurfaceTe某ture(int te某Name)。
它接受一个纹理ID作为参数,并创建一个与该纹理ID相关联的SurfaceTe某ture实例。
2. updateTe某Image:void updateTe某Image(。
此方法用于在SurfaceTe某ture实例上更新纹理图像。
这个方法通常由SurfaceTe某ture的消费者(例如OpenGL ES渲染器)调用来获取最新的纹理图像。
3. getTransformMatri某:void getTransformMatri某(float[] mt 某)。
此方法返回一个4某4纹理变换矩阵,将纹理坐标系转换为SurfaceTe某ture坐标系。
这在OpenGL ES中渲染纹理时非常有用。
4. setOnFrameAvailableListener:void setOnFrameAvailableListener(SurfaceTe某ture.OnFrameAvailableListener listener)。
此方法允许注册一个回调监听器,以便在新的可用帧时被调用。
这样消费者就可以知道何时可以得到最新的纹理图像,而不是轮询。
5. getTimestamp:long getTimestamp(。
返回SurfaceTe某ture中最后一帧的时间戳。
这对于处理实时图像流时非常重要,以确保帧的正确顺序和时序。
使用SurfaceTe某ture处理实时图像流的一般步骤如下:1. 创建一个SurfaceTe某ture对象,并使用纹理ID作为参数进行初始化。
Android之SurfaceView详解

Android之SurfaceView详解展开全文SurfaceView介绍通常情况程序的View和用户响应都是在同一个线程中处理的,这也是为什么处理长时间事件(例如访问网络)需要放到另外的线程中去(防止阻塞当前UI线程的操作和绘制)。
但是在其他线程中却不能修改UI元素,例如用后台线程更新自定义View(调用View的在自定义View中的onDraw函数)是不允许的。
如果需要在另外的线程绘制界面、需要迅速的更新界面或则渲染UI界面需要较长的时间,这种情况就要使用SurfaceView了。
SurfaceView中包含一个Surface对象,而Surface是可以在后台线程中绘制的。
Surface属于 OPhone底层显示系统。
SurfaceView 的性质决定了其比较适合一些场景:需要界面迅速更新、对帧率要求较高的情况。
使用SurfaceView需要注意以下几点情况:SurfaceView和SurfaceHolder.Callback函数都从当前SurfaceView 窗口线程中调用(一般而言就是程序的主线程)。
有关资源状态要注意和绘制线程之间的同步。
在绘制线程中必须先合法的获取Surface 才能开始绘制内容,在SurfaceHolder.Callback.surfaceCreated() 和SurfaceHolder.Callback.surfaceDestroyed()之间的状态为合法的,另外在Surface类型为SURFACE_TYPE_PUSH_BUFFERS时候是不合法的。
额外的绘制线程会消耗系统的资源,在使用SurfaceView的时候要注意这点。
使用SurfaceView 只要继承SurfaceView类并实现SurfaceHolder.Callback接口就可以实现一个自定义的SurfaceView 了,SurfaceHolder.Callback在底层的Surface状态发生变化的时候通知View,SurfaceHolder.Callback具有如下的接口:surfaceCreated(SurfaceHolder holder):当Surface第一次创建后会立即调用该函数。
android hwc service的处理流程

android hwc service的处理流程Android HWC Service的处理流程概述Android HWC(Hardware Composer)Service是Android系统中负责处理图形合成和显示的重要组件之一。
它负责接收来自应用程序和系统服务的请求,将图形元素合成为最终的图像帧,并通过硬件接口将图像显示到屏幕上。
本文将详细说明Android HWC Service的处理流程。
流程一:接收请求在Android系统中,应用程序和系统服务通过SurfaceFlinger将图形请求发送给HWC Service。
HWC Service会按照请求的先后顺序接收并处理这些请求。
流程二:合成图像HWC Service将接收到的多个图形请求进行合成,生成最终的图像帧。
图像合成过程包括以下几个步骤: - 图层排序:根据每个图层的显示顺序和属性,对所有图层进行排序,确定它们在最终图像中的叠放次序。
- 图层合成:将排序后的图层依次合成到一个缓冲区中。
在合成过程中,HWC Service可能会使用硬件加速功能,例如GPU加速,以提高合成效率。
- 混合模式:根据每个图层的设置,将它们合成到最终图像中,并应用相应的混合模式,例如正常混合、透明混合等。
流程三:交给显示引擎合成完成后,HWC Service将最终的图像帧交给显示引擎,通过硬件接口将图像显示到屏幕上。
流程四:VSync同步为了保证图像显示的流畅性,Android系统采用了VSync(垂直同步)机制。
HWC Service会监听VSync信号,并在信号到来时将当前的图像帧发送到显示引擎,以进行显示。
这样,图像的更新频率将与显示设备的刷新率保持同步,避免出现画面撕裂等问题。
结论通过以上的流程,Android HWC Service可以高效地处理图形合成和显示任务,确保应用程序和系统界面在屏幕上的流畅显示。
了解HWC Service的处理流程对于开发者来说是非常重要的,可以帮助他们优化图形渲染和图层合成的性能,提升用户体验。
AndroidWMS窗口管理(二)
...................... mSurfaceController = new WindowSurfaceController(mSession.mSurfaceSession,
attrs.getTitle().toString(),width, height, format, flags, this, windowType, ownerUid); mSurfaceFormat = format; w.setHasSurface(true); } .................................. mService.openSurfaceTransaction(); try { mSurfaceController.setPositionInTransaction(mTmpSize.left, mTmpSize.top, false); mSurfaceController.setLayerStackInTransaction(getLayerStack()); mSurfaceController.setLayer(mAnimLayer); } finally { mService.closeSurfaceTransaction(); } mLastHidden = true; return mSurfaceController; }
屏幕刷新原理
屏幕刷新原理说到界⾯卡顿,基本上就是两个原因:CPU耗时任务、GPU渲染耗时。
优化⽅案基本也是从这两个⽅向⼊⼿。
但是为什么耗时的操作会导致丢帧?以及撕裂是怎么出现的?单缓冲、⼆级缓冲、三缓冲⼜是什么?我们知道在整个显⽰过程中,需要 CPU、GPU、显⽰屏三个模块协调⼯作,⼤致流程如下:1. CPU 负责计算数据,把计算好数据交给 GPU2. GPU 会对图形数据进⾏渲染,渲染好后放到缓冲区 buffer ⾥存起来3. 显⽰屏以特定的把 buffer ⾥的数据呈现到屏幕上屏幕发光原理我们先了解⼀下,⼏种屏幕的发光原理,⽅⾯后⾯理解屏幕刷新流程:CRT 显⽰器由很多荧光点组成,发光管是⼀个射线管,靠电⼦束⾼速击打荧光粉发光(据说离的太近,会有辐射)LED 显⽰器是靠⼆极管发光,⼀直常亮的,⾃⾝有固定的刷新率(⼀般是 60HZ)屏幕刷新过程从发光原理来看,我们知道有⼀个电⼦束(类似扫描抢)的东西存在,屏幕的刷新就从这开始了:从初始位置(第⼀⾏左上⾓)开始扫描,从左到右,进⾏⽔平扫描(Horizontal Scanning)每⼀⾏扫描完成,扫描线会切换到下⼀⾏起点,这个切换过程叫做⽔平消隐,简称 hblank(horizontal blank interval),并发送⽔平同步信号(horizontal synchronization,⼜称⾏同步)依次类推,整个屏幕(⼀个垂直周期)扫描完成后,显⽰器就可以呈现⼀帧的画⾯屏幕最后⼀⾏(⼀个垂直周期)扫描完成后,需要重返左上⾓初始位置,这个过程叫垂直消隐,简称 vblank(vertical blank interval)扫描线回到初始位置之后,准备扫描下⼀帧,同时发出垂直同步信号(vertical synchronization,⼜称场同步)。
这⾥解释⼀下⼏个名词:# 垂直消隐完成⼀帧的扫描后,扫描点会回到初始点,准备扫描下⼀帧,这个过程会花⼀点时间,会有短暂的空⽩期。
android cardview 原理
android cardview 原理Android 中的CardView 是一个UI 组件,用于实现卡片式界面的设计。
它的原理涉及到布局、绘制和阴影效果等方面。
下面是关于Android CardView 的原理的详细说明。
1. CardView 的引入CardView 是Android Material Design 设计风格的一部分,最早引入在Android 5.0(API级别21)及以上版本。
它提供了一种简单而灵活的方式来创建卡片式布局,使得应用界面更加美观和具有层次感。
要使用CardView,首先需要在应用的build.gradle 文件中添加依赖:gradleimplementation 'androidx.cardview:cardview:1.0.0'2. XML 布局中的CardView在布局文件中使用CardView 时,需要将要包含在卡片中的其他视图放置在CardView 中。
例如:xml<androidx.cardview.widget.CardViewandroid:layout_width="match_parent"android:layout_height="wrap_content"android:layout_margin="16dp"app:cardCornerRadius="8dp"app:cardElevation="4dp"><!-- 其他视图放置在CardView 中--><TextViewandroid:layout_width="match_parent"android:layout_height="wrap_content"android:text="Card Content"/></androidx.cardview.widget.CardView>上述示例中,CardView 包含了一个TextView,你可以在CardView 中放置任何其他布局。
surfaceview 用法
surfaceview 用法SurfaceView是Android中的一个视图控件,它可以在一个独立的线程中绘制图形,适用于需要频繁更新UI的场景,比如游戏开发、视频播放等。
在使用SurfaceView时,我们需要了解它的用法和一些常见的操作。
一、SurfaceView的基本用法1. 在布局文件中添加SurfaceView控件:```xml<SurfaceViewandroid:id="@+id/surfaceView"android:layout_width="match_parent"android:layout_height="match_parent" />```2. 在Activity中获取SurfaceView控件的引用:```javaSurfaceView surfaceView = findViewById(R.id.surfaceView);```3. 创建一个继承自SurfaceView的自定义视图类:```javapublic class MySurfaceView extends SurfaceView implementsSurfaceHolder.Callback {private SurfaceHolder surfaceHolder;public MySurfaceView(Context context) {super(context);init();}public MySurfaceView(Context context, AttributeSet attrs) { super(context, attrs);init();}private void init() {surfaceHolder = getHolder();surfaceHolder.addCallback(this);}@Overridepublic void surfaceCreated(SurfaceHolder holder) {// SurfaceView创建时调用,可以在这里进行绘制操作}@Overridepublic void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {// SurfaceView尺寸发生变化时调用,可以在这里进行绘制操作}@Overridepublic void surfaceDestroyed(SurfaceHolder holder) {// SurfaceView销毁时调用,可以在这里释放资源}}```4. 在Activity中使用自定义的SurfaceView:```javaMySurfaceView mySurfaceView = new MySurfaceView(this);```5. 将自定义的SurfaceView添加到布局中:```javaFrameLayout frameLayout = findViewById(R.id.frameLayout); frameLayout.addView(mySurfaceView);二、SurfaceView的绘制操作1. 在surfaceCreated()方法中获取Canvas对象,并进行绘制操作:```java@Overridepublic void surfaceCreated(SurfaceHolder holder) {Canvas canvas = surfaceHolder.lockCanvas();// 进行绘制操作surfaceHolder.unlockCanvasAndPost(canvas);}```2. 在surfaceChanged()方法中获取Canvas对象,并进行绘制操作:```java@Overridepublic void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {Canvas canvas = surfaceHolder.lockCanvas();// 进行绘制操作surfaceHolder.unlockCanvasAndPost(canvas);}```3. 在surfaceDestroyed()方法中释放资源:```java@Overridepublic void surfaceDestroyed(SurfaceHolder holder) { // 释放资源}```三、SurfaceView的常见操作1. 设置背景颜色:```javasurfaceView.setBackgroundColor(Color.RED);```2. 设置透明度:```javasurfaceView.setAlpha(0.5f);```3. 设置可见性:```javasurfaceView.setVisibility(View.VISIBLE);```4. 设置Z轴顺序:```javasurfaceView.setZOrderOnTop(true);```5. 设置点击事件:```javasurfaceView.setOnClickListener(new View.OnClickListener() { @Overridepublic void onClick(View v) {// 处理点击事件}});```6. 设置触摸事件:```javasurfaceView.setOnTouchListener(new View.OnTouchListener() { @Overridepublic boolean onTouch(View v, MotionEvent event) { // 处理触摸事件return true;}});```总结:SurfaceView是Android中用于频繁更新UI的一个视图控件,它可以在独立的线程中进行绘制操作。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
SurfaceView在Android中用作游戏开发是最适宜的,本文就将演示游戏开发中常用的两种绘图刷新策略在SurfaceView中的实现方法。
首先我们来看一下本例需要用到的两个素材图片:
bj.jpg就是一个渐变图,用作背景。
question.png是一个半透明的图像,我们希望将它放在上面,围绕其圆心不断旋转。
实现代码如下:
package SkyD.SurfaceViewTest;
import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.os.Bundle;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
publicclass Main extends Activity {
@Override
publicvoid onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(new MySurfaceView(this));
}
// 自定义的SurfaceView子类
class MySurfaceView extends SurfaceView implements SurfaceHolder.Callb ack {
// 背景图
private Bitmap BackgroundImage;
// 问号图
private Bitmap QuestionImage;
SurfaceHolder Holder;
public MySurfaceView(Context context) {
super(context);
BackgroundImage= BitmapFactory.decodeResource(getResources(),
R.drawable.bg);
QuestionImage= BitmapFactory.decodeResource(getResources(),
R.drawable.question);
Holder = this.getHolder();// 获取holder
Holder.addCallback(this);
}
@Override
publicvoid surfaceChanged(SurfaceHolder holder, int format, int width,
int height) {
// TODO Auto-generated method stub
}
@Override
publicvoid surfaceCreated(SurfaceHolder holder) {
// 启动自定义线程
new Thread(new MyThread()).start();
}
@Override
publicvoid surfaceDestroyed(SurfaceHolder holder) {
// TODO Auto-generated method stub
}
// 自定义线程类
class MyThread implements Runnable {
@Override
publicvoid run() {
Canvas canvas = null;
int rotate = 0;// 旋转角度变量
while (true) {
try {
canvas = Holder.lockCanvas();// 获取画布
Paint mPaint = new Paint();
// 绘制背景
canvas.drawBitmap(BackgroundImage, 0, 0, mPaint);
// 创建矩阵以控制图片旋转和平移
Matrix m = new Matrix();
// 设置旋转角度
m.postRotate((rotate += 48) % 360,
QuestionImage.getWidth() / 2,
QuestionImage.getHeight() / 2);
// 设置左边距和上边距
m.postTranslate(47, 47);
// 绘制问号图
canvas.drawBitmap(QuestionImage, m, mPaint);
// 休眠以控制最大帧频为每秒约30帧
Thread.sleep(33);
} catch (Exception e) {
} finally {
Holder.unlockCanvasAndPost(canvas);// 解锁画布,提交画好的图像
}
}
}
}
}
}
模拟器中的运行效果:
(注:图中的问号图形是在不断旋转中的)
这看起来不错,但是有一个问题:我们在代码中设置的帧频最大值是每秒30帧,而实际运行时的帧频根据目测就能看出是到不了30帧的,这是因为程序在每一帧都要对整个画面进行重绘,过多的时间都被用作绘图处理,所以难以达到最大帧频。
脏矩形刷新
接下来我们将采取脏矩形刷新的方法来优化性能,所谓脏矩形刷新,意为仅刷新有新变化的部分所在的矩形区域,而其他没用的部分就不去刷新,以此来减少资源浪费。
我们可以通过在获取Canvas画布时,为其指派一个参数来声明我们需要画布哪个局部,这样就可以只获得这个部分的控制权:
在这里为了便于观察,我将矩形区域设定为问号图形的1/4区域,也就是说在整个画面中我们仅仅更新问号图形的1/4大小那么点区域,其执行效果为:
可以看到,仅有那1/4区域在快速刷新,其他部分都是静止不动的了,现在的刷新帧频差不多已经能达到最大帧频了,我们的优化起作用了:)
不过别高兴的太早,实际上如果把刷新区域扩大到整个问号图形所在的矩形区域的话,你会发现优化作用变得微乎其微了,还是没法达到最大帧频的,因为更新区域增大了3倍,带来的资源消耗也就大幅增加。
覆盖刷新
这种情况下就应当考虑结合覆盖刷新方法再进一步优化了。
试想一下,我们每次刷新时最大的消耗在哪?
没错,在背景图绘制上,这个绘制区域非常大,会消耗我们很多资源,但实际上背景图在此例中是从不变化的,也就是说我们浪费了很多资源在无用的地方。
那么可不可以只绘制一次背景,以后每次都只绘制会动的问号图形呢?
完全可以,尝试修改一下代码,再前面加一个帧计数器,然后我们仅在第一帧的时候绘制背景:
这样很简单,但是改后直接运行的话你会发现一个奇怪的状况:
问号图案会变得有残影了。
啊哈,这正是我使用半透明图案做范例的目的,通过这个重影,我们就能看出,覆盖刷新其实就是将每次的新的图形绘制到上一帧去,所以如果图像是半透明的,就要考虑重复叠加导致的问题了,而如果是完全不透明的图形则不会有任何问题。
背景会在背景图和黑色背景之间来回闪。
这个问题其实是源于SurfaceView的双缓冲机制,我理解就是它会缓冲前两帧的图像交替传递给后面的帧用作覆盖,这样由于我们仅在第一帧绘制了背景,第二帧就是无背景状态了,且通过双缓冲机制一直保持下来,解决办法就是改为在前两帧都进行背景绘制:
现在就没有问题了(如果换成个不透明的图形的话就真没问题了):
现在虽然还是达不到最大帧频,但是也算不错啦,在真机上跑的会更快些,接近最大帧频了。
结语
我这也是刚接触Android开发,分享这点心得出来,有写的不对的欢迎指点一二^^。