自定义博客皮肤VIP专享

*博客头图:

格式为PNG、JPG,宽度*高度大于1920*100像素,不超过2MB,主视觉建议放在右侧,请参照线上博客头图

请上传大于1920*100像素的图片!

博客底图:

图片格式为PNG、JPG,不超过1MB,可上下左右平铺至整个背景

栏目图:

图片格式为PNG、JPG,图片宽度*高度为300*38像素,不超过0.5MB

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

-+
  • 博客(71)
  • 收藏
  • 关注

原创 Android软件渲染流程

生产消费模型中的图像缓存Surface中管理的图像缓存Surface暴露给Canvas的图像缓存提交给消费者处理的图像缓存Canvas是对Surface提供的图像缓存的抽象封装。Surface对Canvas初始化的过程,就是Surface从生产消费模型中为Canvas分配一块图像缓存的过程。一个Surface同一时间只能提供一个图像缓存。

2024-05-22 14:53:07 631

原创 Android图像缓存与Surface初始化

在Android系统中,绘制渲染与渲染管理是分开的,分别由Surface和SurfaceControl负责。Surface是SurfaceFlinger管理的一块缓存,Surface的创建依赖SurfaceControl。SurfaceControl用于管理Surface的绘制层级与获取。Surface和SurfaceControl声明在ViewRootImpl的全局成员变量中,在创建ViewRootImpl时会一起创建Surface和SurfaceControl。

2024-05-21 21:39:28 994

原创 Android图像生产消费模型

之后生产者开始绘制。在生产消费模型中,生产者与消费者在接收到VSync信号时开始生产和消费,但由于生产速率与消费速率不同,因此当下一次VSync信号到来时,生产与消费过程不一定都能完成,这时会通过Fence机制来保障生产消费过程的同步。在Android 12之后,生产消费模型由BLASTBufferQueue进行管理,并且将生产消费模型从SurfaceFlinger服务端移动了客户端。1)减轻了SurfaceFlinger的压力,SurfaceFlinger不再需要管理每个Layer中的生产消费模型。

2024-05-20 15:37:27 982

原创 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 665 2

原创 Android图像系统与Choreographer

一个基础的图像显示系统由CPU、GPU、屏幕三部分组成。CPU负责计算帧数据,GPU负责渲染图形数据,屏幕负责图像的显示。在屏幕显示图像时,会按照从上向下逐行扫描的方式扫描每一帧图像的像素。由于CPU与GPU处理数据的时间不可控,因此会导致屏幕刷新率与渲染帧率不一致。具体表现为在扫描第一帧图像扫描的过程中出现第二帧图像,引起屏幕中画面的撕裂。

2024-05-17 21:28:48 691

原创 音视频基础

当帧率固定时,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 793

原创 【Android】点击短信链接唤起APP的方案实践

在很多业务场景中,需要点击短信链接跳转到App的指定页面。在Android系统中,想要实现这个功能,可以通过DeepLink或AppLink实现。 DeepLink是Android系统最基础、最普遍、最广泛的外部唤起App的方式,不受系统版本限制。 当用户点击链接时,系统会弹出弹窗让用户选择使用哪个App来处理这个链接,如下图所示: 在AndroidManifest文件中需要唤起的activity中加入intent-filter,监听对应的链接。代码如下: 注意:由于一个inte

2023-10-09 10:02:07 2985 1

原创 Less简明教程

Less教程

2023-06-30 15:49:34 901 1

原创 Kotlin Coroutine‘s Secret

Kotlin协程:协程的基础与使用 Kotlin协程:协程上下文与上下文元素 Kotlin协程:续体、续体拦截器、调度器 Kotlin协程:创建、启动、挂起、恢复 Kotlin协程:生命周期原理 Kotlin协程:父子协程的绑定与传递 Kotlin协程:线程的桥接与切换 Kotlin协程:受限协程作用域与序列发生器 Kotlin协程:异步执行与同步获取 Kotlin协程:Dispatchers.IO线程池原理 Kotlin协程:异常处理机制

2022-10-07 18:27:55 1022 1

原创 Kotlin协程:冷流转换热流的使用与原理

shareIn方法与stateIn方法的使用与实现的原理类似,下面以shareIn方法为例进行分析。

2022-10-02 18:46:56 2444

原创 Kotlin协程:MutableStateFlow的实现原理

在在MutableStateFlow方法中,根据参数value创建并返回一个类型为StateFlowImpl的对象,如果参数value为空,则传入对应的标识NULL。

2022-09-25 16:43:44 4066

原创 Kotlin协程:StateFlow的设计与使用

StateFlow是一种单数据更新的热流,通过emit方法更新StateFlow的数据,通过value属性可以获取当前的数据。

2022-09-25 15:58:49 2543

原创 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 2077

原创 Koltin协程:异步热数据流的设计与使用

通过使用协程中提供的flow方法可以创建一个Flow对象。$it$it在上面的代码中,通过调用flow方法,构建了一个名为flow对象,并对flow对象异步执行了两次。每次都会打印出1、2、3、4,然后结束执行。无论谁在前谁在后,无论执行多少次,得到的结果都是相同的,这就是异步冷数据流的一个特点。

2022-09-18 17:13:18 535

原创 Kotlin协程:Flow的流式调用原理

Kotlin协程:Flow的流式调用原理在协程Flow中,除了flow方法外的其他方法,都是Flow接口的扩展方法,这些方法也被称作操作符。而flow方法用于创建一个类型为Flow的对象,一般用于创建整条链中的第一个Flow对象。除了collect方法外的其他方法,在被调用后都会返回一个Flow对象。这里的collect方法不是在Flow接口中定义的方法,而是Flow接口的扩展方法,一个操作符,一般用于在整条链创建完毕后,最为最后一个操作符调用,触发整条链的执行。

2022-09-13 10:47:07 792

原创 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 1173

原创 Koltin协程:Flow的触发与消费

在协程中,其实还提供了分离流的触发与消费的操作——onEach方法。通过使用onEach方法,可以将原本在collect方法中的消费过程的移动到onEach方法中。这样在构建好一个Flow对象后,不会立刻去执行onEach方法,只有当调用collect方法时,才会真正的去触发流的执行。这样就实现了流的触发与消费的分离。

2022-09-04 15:34:56 788

原创 Kotlin协程:flowOn与线程切换

在flowOn方法中,首先会检查方法所在的协程是否执行结束。如果没有结束,则会执行判断语句,这里flowOn方法传入的上下文不是空上下文,且通过flow方法构建出的Flow对象也不是FusibleFlow类型的对象,因此这里会走到else分支,将上游flow方法创建的Flow对象和上下文包装成ChannelFlowOperatorImpl类型的对象。

2022-09-03 20:43:14 1552

原创 Kotlin协程:Flow的融合、Channel容量、溢出策略

当需要进行协程间的通信时,可以调用Channel方法,创建一个Channel接口指向的对象,通过调用该对象的send方法和receive方法实现消息的发送与接收。协程对Channel接口的实现,本质上与阻塞队列类似,这里不再赘述。......

2022-08-31 09:46:44 812

原创 Kotlin协程:Flow基础原理

AbstractFlow类是一个抽象类,实现了Flow接口和CancellableFlow接口。// 核心方法 @InternalCoroutinesApi public final override suspend fun collect(collector : FlowCollector < T >) {

2022-08-30 20:32:07 963

原创 Kotlin协程:异常处理机制

Koltin协程:异常处理机制 当一个协程执行过程中遇到未捕获的异常时,首先会尝试将异常传递给自己的父协程,最终传递给最顶级的父协程。如果父协程不处理(父协程为SupervisorJob或为async启动的协程),则由自身上下文中的异常处理器处理,如果自身上下文没有异常处理器,则会同时交给JVM全局的异常处理器和当前线程的uncaughtExceptionHandler处理。对于通过launch方法启动的协程,在执行过程中遇到未捕获异常时会直接抛出。

2022-08-24 09:51:50 742

原创 Kotlin协程:Dispatchers.IO线程池原理

Kotlin协程:Dispatchers.IO线程池原理分析 CoroutineScheduler类是核心的线程池,用于任务的执行。LimitingDispatcher类对CoroutineScheduler类进行代理,是CoroutineScheduler类尾调机制的使用者,对任务进行初步排队。

2022-08-23 21:09:37 2815

原创 Kotlin协程:异步执行与同步获取

在协程中,可以通过async方法开启一个协程,执行任务。但与launch方法不同的是,async方法会返回一个Deferred接口指向的对象,通过调用找个对象的await方法,可以获取任务的执行结果,如果这时任务没有结束,await方法还会同步挂起等待任务执行完毕返回结果再继续执行。async方法启动协程的逻辑与launch方法是相同的,launch方法在中分析过。...

2022-08-14 16:47:31 4315

原创 Kotlin协程:受限协程作用域与序列发生器

当使用序列发生器进行迭代时,首先会调用hasNext方法,hasNext方法会通过保存的续体,恢复序列发生器所在的协程继续执行,获取下一次待发射的数据。如果获取了到数据,则会返回true,这样之后通过next方法就可以获取到对应的数据。当序列发生器所在的协程在执行中遇到yield方法时,会发生挂起,同时将下一次待发射的数据保存起来。如果遇到的是yieldAll方法,则保存的是迭代器,下一次发射数据时会从迭代器中获取。...

2022-08-13 19:40:42 557

原创 Kotlin协程:线程的桥接与切换

Kotlin协程:作用域协程、线程的桥接与切换

2022-08-13 18:15:01 1159

原创 Kotlin协程:父子协程的绑定与传递

之前在这里与之前在中分析的协程生命周期方法类似,也是将父子协程封装成ChildHandleNode对象,之后进行类型转换。最终通过invokeOnCompletion方法获取ChildHandle对象。这里的逻辑可以理解成子协程监听父协程完成。......

2022-08-08 14:29:19 648

原创 Kotlin协程:生命周期原理

start方法用于启动协程,对于已经启动的协程,再次调用它的start方法是没有意义的。默认情况下,协程在创建后会自动启动。而根据上一篇的分析,如果协程按照LAZY模式启动,则需要手动去调用它的start方法。接下来以launch方法为例,分析LAZY启动模式下协程的启动。LazyStandaloneCoroutine类内部只对协程进行了创建,但并没有启动,只有当手动去调用start方法后才会启动。......

2022-08-07 18:56:07 982

原创 Kotlin协程:创建、启动、挂起、恢复

Kotlin协程:创建、启动、挂起、恢复

2022-07-31 20:44:24 1663

原创 Kotlin协程:续体、续体拦截器、调度器

为什么协程需要EventLoop呢?协程的本质是续体传递,而续体传递的本质是回调,假设在Dispatchers.Unconfined调度下,要连续执行多个suspend方法,就会有多个续体传递,假设suspend方法达到一定数量后,就会造成StackOverflow,进而引起崩溃。同样的,我们知道调用runBlocking会阻塞当前线程,而runBlocking阻塞的原理就是执行“死循环”,因此需要在循环中做任务的分发,去执行内部协程在Dispatchers.Unconfined调度器下加入的任务。...

2022-07-31 12:29:36 564

原创 Kotlin协程:协程上下文与上下文元素

协程上下文的原理与继承关系,上下文元素的组合原理。

2022-07-30 21:30:46 746

原创 Kotlin协程:协程的基础与使用

协程是Coroutine的中文简称,co表示协同、协作,routine表示程序。协程可以理解为多个互相协作的程序。协程是轻量级的线程,它的轻量体现在启动和切换,协程的启动不需要申请额外的堆栈空间;协程的切换发生在用户态,而非内核态,避免了复杂的系统调用。...

2022-07-24 19:39:47 15257 5

原创 Android架构演进史

Android历史架构演进:MVC、MVP、MVVM、Clean、MVI。

2022-07-23 20:10:34 1424 2

原创 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 599

原创 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 434

原创 【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 276

原创 【Java】JDK源码分析——Thread

Thread源码分析一.概述二.源码解析1.重要的全局变量2.内部枚举类State3. nextThreadNum方法4. nextThreadID方法5.常用的构造方法1)无参数2)参数为Runnable3)参数为String4)参数为ThreadGroup、Runnable、String、long5)四个参数的init方法6)五个参数的init方法6. currentThread方法7. setPriority方法1)checkAccess方法2)getThreadGroup方法3)setPriorit

2020-06-20 20:08:10 234

原创 【Java】JDK源码分析——Short

Short源码分析一.概述二.源码分析1.全局变量2.静态内部类ShortCache3.构造方法1)参数为short2)参数为String4. parseShort方法5. valueOf方法6. decode方法7. byteValue方法8. shortValue方法9. intValue方法10. longValue方法11. floatValue方法12. doubleValue方法13. toString方法1)无参数2)参数为byte14. hashCode方法1)hashCode方法15. e

2020-06-19 21:39:00 243

原创 【Java】JDK源码分析——Long

Long源码分析一.概述二.源码分析1.全局变量2.静态内部类3.构造方法1)参数为long2)参数为String4. parseLong方法5. parseUnsignedLong方法6. valueOf方法1)参数为String指定进制数:不指定进制数:2)参数为int7. byteValue方法8. shortValue方法9. intValue方法10. longValue方法11. floatValue方法12. doubleValue方法13. toString方法1)无参数2)参数为longa

2020-06-19 21:24:54 337

原创 【Java】JDK源码分析——Integer

Integer源码分析一.概述二.源码分析1.全局变量2.静态内部类IntegerCache3.构造方法1)参数为int2)参数为String4. parseInt方法5. parseUnsignedInt方法6. valueOf方法1)参数为String指定进制数:不指定进制数:2)参数为int7. byteValue方法8. shortValue方法9. intValue方法10. longValue方法11. floatValue方法12. doubleValue方法13. toString方法1)无

2020-06-19 20:23:59 240

原创 【Java】JDK源码分析——Number

Number源码分析一.概述二.源码分析1.全局变量2. intValue方法3. longValue方法4. floatValue方法5. doubleValue方法6. byteValue方法7. shortValue方法一.概述Number是一个抽象类,表示数值,它是所有表示数值的类的超类。Byte、Double、Float、Integer、Long、Short都继承该类。Number类一共只有6个方法,这些方法用来是实现不同数值类型的转换。Number.java中的相关代码:public a

2020-06-19 19:44:12 252

空空如也

空空如也

TA创建的收藏夹 TA关注的收藏夹

TA关注的人

提示
确定要删除当前文章?
取消 删除