- 博客(76)
- 收藏
- 关注
原创 Android子线程更新View的方法原理
ViewRootImpl在UI线程中被创建,并在构造方法中保存了当前线程的引用(mThread)。在每次更新View时,通过调用View的invalidate方法或requestLayout方法触发ViewRootImpl的checkThread方法,验证调用线程是否与mThread一致。
2025-03-13 17:25:47
878
原创 SurfaceView与TextureView的绘制渲染
1.SurfaceView的初始化SurfaceView的初始化流程发生在首次绘制前。1.1 SurfaceControl的创建SurfaceView在初始化过程中会创建三个SurfaceControl节点:容器节点、绘制节点、背景节点。首先会在ViewRootImpl的SurfaceControl节点下创建SurfaceView的容器节点,然后在SurfaceView的容器节点下创建SurfaceView的绘制节点和SurfaceView的背景节点。1.2 Surface的初始化SurfaceV
2024-05-29 11:27:20
1615
原创 Android硬件渲染流程
Android硬件渲染分成两个部分:渲染指令列表的构建和渲染指令列表的渲染,分别对应着ThreadedRenderer的updateRootDisplayList方法和syncAndDrawFrame方法。即绘制过程和渲染过程是分开的。绘制过程发生在UI线程,渲染过程发生在Render线程。
2024-05-26 18:36:16
1754
原创 Android硬件渲染环境初始化
硬件渲染的开启发生在ViewRootImpl中。开启硬件渲染会进行两步操作:第一步是ThreadedRenderer的创建,第二步是ThreadedRenderer与Surface的绑定。
2024-05-24 23:29:30
1501
原创 Android软件渲染流程
生产消费模型中的图像缓存Surface中管理的图像缓存Surface暴露给Canvas的图像缓存提交给消费者处理的图像缓存Canvas是对Surface提供的图像缓存的抽象封装。Surface对Canvas初始化的过程,就是Surface从生产消费模型中为Canvas分配一块图像缓存的过程。一个Surface同一时间只能提供一个图像缓存。
2024-05-22 14:53:07
2091
原创 Android图像缓存与Surface初始化
在Android系统中,绘制渲染与渲染管理是分开的,分别由Surface和SurfaceControl负责。Surface是SurfaceFlinger管理的一块缓存,Surface的创建依赖SurfaceControl。SurfaceControl用于管理Surface的绘制层级与获取。Surface和SurfaceControl声明在ViewRootImpl的全局成员变量中,在创建ViewRootImpl时会一起创建Surface和SurfaceControl。
2024-05-21 21:39:28
1649
原创 Android图像生产消费模型
之后生产者开始绘制。在生产消费模型中,生产者与消费者在接收到VSync信号时开始生产和消费,但由于生产速率与消费速率不同,因此当下一次VSync信号到来时,生产与消费过程不一定都能完成,这时会通过Fence机制来保障生产消费过程的同步。在Android 12之后,生产消费模型由BLASTBufferQueue进行管理,并且将生产消费模型从SurfaceFlinger服务端移动了客户端。1)减轻了SurfaceFlinger的压力,SurfaceFlinger不再需要管理每个Layer中的生产消费模型。
2024-05-20 15:37:27
1346
原创 VSync信号系统与SurfaceFlinger
VSync信号分为两种:硬件VSync信号HW-VSync和软件VSync信号SW-VSync。SW-VSync信号由SW-VSync模型产生。HW-VSync信号负责对SW-VSync模型进行校准。系统中分发的VSync信号是SW-VSync信号。SW-VSync信号的分发采用单次申请回调制,一次申请对应一次回调,不申请则没有回调。
2024-05-19 21:38:21
1908
2
原创 Android图像系统与Choreographer
一个基础的图像显示系统由CPU、GPU、屏幕三部分组成。CPU负责计算帧数据,GPU负责渲染图形数据,屏幕负责图像的显示。在屏幕显示图像时,会按照从上向下逐行扫描的方式扫描每一帧图像的像素。由于CPU与GPU处理数据的时间不可控,因此会导致屏幕刷新率与渲染帧率不一致。具体表现为在扫描第一帧图像扫描的过程中出现第二帧图像,引起屏幕中画面的撕裂。
2024-05-17 21:28:48
1096
原创 音视频基础
当帧率固定时,GOP越大,压缩率越低,平均每帧数据越大,图像质量越高。GOP一般由M和N表示,M是I帧和P帧之间的距离,N是两个I帧之间的距离。BPS是码率,即一秒钟传输数据量的大小,BPS受分辨率、帧率等多种因素影响,BPS的大小影响传输时的网络带宽。H.264是一种编码标准,在编码的过程中会对视频数据(I帧、P帧、B帧)进行压缩。MP4是一种音视频媒体格式,用于对编码后的音频数据与视频数据封装,指导播放器如何音频数据与视频数据。音频采集后的数据为PCM数据,视频采集完的数据为YUV格式图像数据。
2024-05-17 15:52:21
1107
原创 【Android】点击短信链接唤起APP的方案实践
在很多业务场景中,需要点击短信链接跳转到App的指定页面。在Android系统中,想要实现这个功能,可以通过DeepLink或AppLink实现。 DeepLink是Android系统最基础、最普遍、最广泛的外部唤起App的方式,不受系统版本限制。 当用户点击链接时,系统会弹出弹窗让用户选择使用哪个App来处理这个链接,如下图所示: 在AndroidManifest文件中需要唤起的activity中加入intent-filter,监听对应的链接。代码如下: 注意:由于一个inte
2023-10-09 10:02:07
4559
1
原创 Kotlin Coroutine‘s Secret
Kotlin协程:协程的基础与使用 Kotlin协程:协程上下文与上下文元素 Kotlin协程:续体、续体拦截器、调度器 Kotlin协程:创建、启动、挂起、恢复 Kotlin协程:生命周期原理 Kotlin协程:父子协程的绑定与传递 Kotlin协程:线程的桥接与切换 Kotlin协程:受限协程作用域与序列发生器 Kotlin协程:异步执行与同步获取 Kotlin协程:Dispatchers.IO线程池原理 Kotlin协程:异常处理机制
2022-10-07 18:27:55
1083
原创 Kotlin协程:冷流转换热流的使用与原理
shareIn方法与stateIn方法的使用与实现的原理类似,下面以shareIn方法为例进行分析。
2022-10-02 18:46:56
2745
原创 Kotlin协程:MutableStateFlow的实现原理
在在MutableStateFlow方法中,根据参数value创建并返回一个类型为StateFlowImpl的对象,如果参数value为空,则传入对应的标识NULL。
2022-09-25 16:43:44
4494
原创 Kotlin协程:StateFlow的设计与使用
StateFlow是一种单数据更新的热流,通过emit方法更新StateFlow的数据,通过value属性可以获取当前的数据。
2022-09-25 15:58:49
3025
原创 Kotlin协程:MutableSharedFlow的实现原理
/ 用于新订阅者申请使用当前AbstractSharedFlowSlot类型的对象 // 返回true代表申请成功,返回false代表申请失败 abstract fun allocateLocked(flow : F) : Boolean // 用于订阅者释放当前使用的AbstractSharedFlowSlot类型得到对象, // 并以数组的形式返回待恢复的续体 abstract fun freeLocked(flow : F) : Array < Continuation < Unit >?> }
2022-09-18 20:11:08
2348
原创 Koltin协程:异步热数据流的设计与使用
通过使用协程中提供的flow方法可以创建一个Flow对象。$it$it在上面的代码中,通过调用flow方法,构建了一个名为flow对象,并对flow对象异步执行了两次。每次都会打印出1、2、3、4,然后结束执行。无论谁在前谁在后,无论执行多少次,得到的结果都是相同的,这就是异步冷数据流的一个特点。
2022-09-18 17:13:18
640
原创 Kotlin协程:Flow的流式调用原理
Kotlin协程:Flow的流式调用原理在协程Flow中,除了flow方法外的其他方法,都是Flow接口的扩展方法,这些方法也被称作操作符。而flow方法用于创建一个类型为Flow的对象,一般用于创建整条链中的第一个Flow对象。除了collect方法外的其他方法,在被调用后都会返回一个Flow对象。这里的collect方法不是在Flow接口中定义的方法,而是Flow接口的扩展方法,一个操作符,一般用于在整条链创建完毕后,最为最后一个操作符调用,触发整条链的执行。
2022-09-13 10:47:07
1075
原创 Kotlin协程:Flow的异常处理
Flow异常处理catch方法 catch方法用于捕获上游流产生的异常,代码如下: catch方法是Flow接口的扩展方法,并返回一个Flow类型的对象。在catch方法中,调用flow方法创建了一个Flow对象。 catch方法核心是通过catchImpl方法实现异常的捕获,如果成功捕获到异常,则回调参数action处理。这里参数action是FlowCollector接口的扩展方法,因此可以继续调用emit方法,向下游发送值。 当下游调用collect方法时,会触发cat
2022-09-13 10:23:31
1496
原创 Koltin协程:Flow的触发与消费
在协程中,其实还提供了分离流的触发与消费的操作——onEach方法。通过使用onEach方法,可以将原本在collect方法中的消费过程的移动到onEach方法中。这样在构建好一个Flow对象后,不会立刻去执行onEach方法,只有当调用collect方法时,才会真正的去触发流的执行。这样就实现了流的触发与消费的分离。
2022-09-04 15:34:56
999
原创 Kotlin协程:flowOn与线程切换
在flowOn方法中,首先会检查方法所在的协程是否执行结束。如果没有结束,则会执行判断语句,这里flowOn方法传入的上下文不是空上下文,且通过flow方法构建出的Flow对象也不是FusibleFlow类型的对象,因此这里会走到else分支,将上游flow方法创建的Flow对象和上下文包装成ChannelFlowOperatorImpl类型的对象。
2022-09-03 20:43:14
1948
原创 Kotlin协程:Flow的融合、Channel容量、溢出策略
当需要进行协程间的通信时,可以调用Channel方法,创建一个Channel接口指向的对象,通过调用该对象的send方法和receive方法实现消息的发送与接收。协程对Channel接口的实现,本质上与阻塞队列类似,这里不再赘述。......
2022-08-31 09:46:44
1024
原创 Kotlin协程:Flow基础原理
AbstractFlow类是一个抽象类,实现了Flow接口和CancellableFlow接口。// 核心方法 @InternalCoroutinesApi public final override suspend fun collect(collector : FlowCollector < T >) {
2022-08-30 20:32:07
1228
原创 Kotlin协程:异常处理机制
Koltin协程:异常处理机制 当一个协程执行过程中遇到未捕获的异常时,首先会尝试将异常传递给自己的父协程,最终传递给最顶级的父协程。如果父协程不处理(父协程为SupervisorJob或为async启动的协程),则由自身上下文中的异常处理器处理,如果自身上下文没有异常处理器,则会同时交给JVM全局的异常处理器和当前线程的uncaughtExceptionHandler处理。对于通过launch方法启动的协程,在执行过程中遇到未捕获异常时会直接抛出。
2022-08-24 09:51:50
1112
原创 Kotlin协程:Dispatchers.IO线程池原理
Kotlin协程:Dispatchers.IO线程池原理分析 CoroutineScheduler类是核心的线程池,用于任务的执行。LimitingDispatcher类对CoroutineScheduler类进行代理,是CoroutineScheduler类尾调机制的使用者,对任务进行初步排队。
2022-08-23 21:09:37
3411
原创 Kotlin协程:异步执行与同步获取
在协程中,可以通过async方法开启一个协程,执行任务。但与launch方法不同的是,async方法会返回一个Deferred接口指向的对象,通过调用找个对象的await方法,可以获取任务的执行结果,如果这时任务没有结束,await方法还会同步挂起等待任务执行完毕返回结果再继续执行。async方法启动协程的逻辑与launch方法是相同的,launch方法在中分析过。...
2022-08-14 16:47:31
4779
原创 Kotlin协程:受限协程作用域与序列发生器
当使用序列发生器进行迭代时,首先会调用hasNext方法,hasNext方法会通过保存的续体,恢复序列发生器所在的协程继续执行,获取下一次待发射的数据。如果获取了到数据,则会返回true,这样之后通过next方法就可以获取到对应的数据。当序列发生器所在的协程在执行中遇到yield方法时,会发生挂起,同时将下一次待发射的数据保存起来。如果遇到的是yieldAll方法,则保存的是迭代器,下一次发射数据时会从迭代器中获取。...
2022-08-13 19:40:42
653
原创 Kotlin协程:父子协程的绑定与传递
之前在这里与之前在中分析的协程生命周期方法类似,也是将父子协程封装成ChildHandleNode对象,之后进行类型转换。最终通过invokeOnCompletion方法获取ChildHandle对象。这里的逻辑可以理解成子协程监听父协程完成。......
2022-08-08 14:29:19
919
原创 Kotlin协程:生命周期原理
start方法用于启动协程,对于已经启动的协程,再次调用它的start方法是没有意义的。默认情况下,协程在创建后会自动启动。而根据上一篇的分析,如果协程按照LAZY模式启动,则需要手动去调用它的start方法。接下来以launch方法为例,分析LAZY启动模式下协程的启动。LazyStandaloneCoroutine类内部只对协程进行了创建,但并没有启动,只有当手动去调用start方法后才会启动。......
2022-08-07 18:56:07
1201
原创 Kotlin协程:续体、续体拦截器、调度器
为什么协程需要EventLoop呢?协程的本质是续体传递,而续体传递的本质是回调,假设在Dispatchers.Unconfined调度下,要连续执行多个suspend方法,就会有多个续体传递,假设suspend方法达到一定数量后,就会造成StackOverflow,进而引起崩溃。同样的,我们知道调用runBlocking会阻塞当前线程,而runBlocking阻塞的原理就是执行“死循环”,因此需要在循环中做任务的分发,去执行内部协程在Dispatchers.Unconfined调度器下加入的任务。...
2022-07-31 12:29:36
729
原创 Kotlin协程:协程的基础与使用
协程是Coroutine的中文简称,co表示协同、协作,routine表示程序。协程可以理解为多个互相协作的程序。协程是轻量级的线程,它的轻量体现在启动和切换,协程的启动不需要申请额外的堆栈空间;协程的切换发生在用户态,而非内核态,避免了复杂的系统调用。...
2022-07-24 19:39:47
16125
5
原创 Android屏幕切换与生命周期的调用总结!!!
Android屏幕切换与生命周期的调用Android屏幕切换与生命周期的调用1.Activity不设置android:configChange属性1)竖屏切换到横屏2)横屏切换到竖屏2.Activity设置属性为android:configChange = "orientation"1)竖屏切换到横屏2)横屏切换到竖屏3.Activity设置属性为android:configChange = "orientation|keyboardHidden|screenSize"(API ≥ 13)或android:
2020-12-13 21:17:00
683
原创 Android跨进程(IPC)通信方法总结!!!
Android IPC方法总结1. Bundle2. 文件共享File3. AIDL4.Messenger5.ContentProvider6.Socket1. Bundle Bundle是Android中提供的用于携带数据通信的类,优点是简单易用,但只能传输基本类型的数据和实现了Parcelable或Serializable接口的对象,及Android中一些特殊的对象。2. 文件共享File 通过使用Jav
2020-12-13 20:45:58
510
原创 【Java】JDK源码分析——ThreadLocal
ThreadLocal源码分析一.概述二.源码分析1.全局变量2. nextHashCode方法3.构造方法4. initialValue方法5. getMap方法6. createMap方法7. createInheritedMap方法8. childValue方法9. remove方法10. set方法11. setInitialValue方法12. get方法13.ThreadLocal中的静态内部类ThreadLocalMap1)全局变量2)ThreadLocalMap中的静态内部类Entry3)构
2020-06-24 07:37:52
334
空空如也
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人