<?xml version="1.0" encoding="utf-8" ?><rss version="2.0"><channel><title><![CDATA[吴延宝]]></title><description><![CDATA[正在输入...]]></description><link>https://blog.youkuaiyun.com/codeyanbao</link><language>zh-cn</language><generator>https://blog.youkuaiyun.com/</generator><copyright><![CDATA[Copyright &copy; codeyanbao]]></copyright><item><title><![CDATA[＜span class=“js_title_inner“＞毫米级剖析：Binder如何实现「一次拷贝」神话？＜/span＞]]></title><link>https://blog.youkuaiyun.com/codeyanbao/article/details/157659208</link><guid>https://blog.youkuaiyun.com/codeyanbao/article/details/157659208</guid><author>codeyanbao</author><pubDate>Wed, 10 Sep 2025 07:03:36 +0800</pubDate><description><![CDATA[客户端进程通过bindService函数调用去连接服务，触发服务Service去Binder驱动注册，生成服务对应的binder_node结构体并加入到服务所在进程的binder_proc的红黑树中，并将服务节点的句柄返回到客户端，客户端通过句柄可以查找到对应的服务引用以及最终的服务节点进行IPC调用。当进程A传递消息到进程B时，第一次拷贝发生在将进程A中的用户空间的数据拷贝到内核空间的消息队列中（1次拷贝），然后再将内核空间的消息队列里的数据拷贝到进程B的用户空间中（2次拷贝）。]]></description><category></category></item><item><title><![CDATA[毫米级剖析：Binder如何实现「一次拷贝」神话？]]></title><link>https://blog.youkuaiyun.com/codeyanbao/article/details/151465008</link><guid>https://blog.youkuaiyun.com/codeyanbao/article/details/151465008</guid><author>codeyanbao</author><pubDate>Wed, 10 Sep 2025 07:03:36 +0800</pubDate><description><![CDATA[客户端进程通过bindService函数调用去连接服务，触发服务Service去Binder驱动注册，生成服务对应的binder_node结构体并加入到服务所在进程的binder_proc的红黑树中，并将服务节点的句柄返回到客户端，客户端通过句柄可以查找到对应的服务引用以及最终的服务节点进行IPC调用。当进程A传递消息到进程B时，第一次拷贝发生在将进程A中的用户空间的数据拷贝到内核空间的消息队列中（1次拷贝），然后再将内核空间的消息队列里的数据拷贝到进程B的用户空间中（2次拷贝）。]]></description><category></category></item><item><title><![CDATA[＜span class=“js_title_inner“＞为什么SurfaceFlinger是Android流畅显示的幕后英雄？合成过程详解＜/span＞]]></title><link>https://blog.youkuaiyun.com/codeyanbao/article/details/157645665</link><guid>https://blog.youkuaiyun.com/codeyanbao/article/details/157645665</guid><author>codeyanbao</author><pubDate>Tue, 26 Aug 2025 08:03:24 +0800</pubDate><description><![CDATA[读者也可以思考一下，本人的一点看法是第一个死循环是保证Scheduler这个线程能一直跟随系统存活（作为图形系统关键的一环），第二个死循环是消息事件的业务逻辑，保证一直能监听到事件消息，当前看起来外层的Scheduler的死循环是冗余的，因为去掉Scheduler的循环，由于waitMessage中会开启死循环，也能保证Scheduler线程持续存活。这里可能是历史代码问题，又或者是一种保护设计，万一后面waitMessage函数的业务逻辑不再是无限循环而影响图形系统的调度模块Scheduler的存活。]]></description><category></category></item><item><title><![CDATA[为什么SurfaceFlinger是Android流畅显示的幕后英雄？合成过程详解]]></title><link>https://blog.youkuaiyun.com/codeyanbao/article/details/150915934</link><guid>https://blog.youkuaiyun.com/codeyanbao/article/details/150915934</guid><author>codeyanbao</author><pubDate>Tue, 26 Aug 2025 08:03:24 +0800</pubDate><description><![CDATA[读者也可以思考一下，本人的一点看法是第一个死循环是保证Scheduler这个线程能一直跟随系统存活（作为图形系统关键的一环），第二个死循环是消息事件的业务逻辑，保证一直能监听到事件消息，当前看起来外层的Scheduler的死循环是冗余的，因为去掉Scheduler的循环，由于waitMessage中会开启死循环，也能保证Scheduler线程持续存活。这里可能是历史代码问题，又或者是一种保护设计，万一后面waitMessage函数的业务逻辑不再是无限循环而影响图形系统的调度模块Scheduler的存活。]]></description><category></category></item><item><title><![CDATA[＜span class=“js_title_inner“＞揭开Android Vulkan渲染封印：帧率暴增的底层指令＜/span＞]]></title><link>https://blog.youkuaiyun.com/codeyanbao/article/details/157646007</link><guid>https://blog.youkuaiyun.com/codeyanbao/article/details/157646007</guid><author>codeyanbao</author><pubDate>Fri, 15 Aug 2025 07:05:38 +0800</pubDate><description><![CDATA[这个函数里调用RenderProxy.cpp的syncAndDrawFrame()函数，syncAndDrawFrame()函数里调用DrawFrameTask.cpp的drawFrame()函数，此函数调用函数当前类的postAndWait()函数，然后函数里调用RenderThread的queue()函数，将当前Task入到渲染线程的队列；那么上文中的mRenderPipeline->draw()函数实际就是SkiaVulkanPipeline->draw()函数调用，draw()函数中调用到。]]></description><category></category></item><item><title><![CDATA[揭开Android Vulkan渲染封印：帧率暴增的底层指令]]></title><link>https://blog.youkuaiyun.com/codeyanbao/article/details/150434375</link><guid>https://blog.youkuaiyun.com/codeyanbao/article/details/150434375</guid><author>codeyanbao</author><pubDate>Fri, 15 Aug 2025 07:05:38 +0800</pubDate><description><![CDATA[这个函数里调用RenderProxy.cpp的syncAndDrawFrame()函数，syncAndDrawFrame()函数里调用DrawFrameTask.cpp的drawFrame()函数，此函数调用函数当前类的postAndWait()函数，然后函数里调用RenderThread的queue()函数，将当前Task入到渲染线程的队列；那么上文中的mRenderPipeline->draw()函数实际就是SkiaVulkanPipeline->draw()函数调用，draw()函数中调用到。]]></description><category></category></item><item><title><![CDATA[＜span class=“js_title_inner“＞60fps背后的秘密：Android图层数据与控制的分离哲学＜/span＞]]></title><link>https://blog.youkuaiyun.com/codeyanbao/article/details/157660702</link><guid>https://blog.youkuaiyun.com/codeyanbao/article/details/157660702</guid><author>codeyanbao</author><pubDate>Tue, 05 Aug 2025 10:05:16 +0800</pubDate><description><![CDATA[这就是主要角色类的实例化的顺序过程。分析：Surface的创建过程中，不得不先分析SurfaceControl和Layer的创建，下图是SurfaceControl的创建过程的简化版（详细的代码细节非常多，不便于大家记忆理解，而且太细节容易让大家脑子更糊涂），其中涉及Binder跨进程调用以及JNI调用等。这个在网上很多博客写的还是上面的流程，包括在23、24年的博客，而且用Deepseek等AI去查，结果都是上面的流程，可见AI不是去查最近的源码库，而是基于网上的博客做整理而已。]]></description><category></category></item><item><title><![CDATA[60fps背后的秘密：Android图层数据与控制的分离哲学]]></title><link>https://blog.youkuaiyun.com/codeyanbao/article/details/149954459</link><guid>https://blog.youkuaiyun.com/codeyanbao/article/details/149954459</guid><author>codeyanbao</author><pubDate>Tue, 05 Aug 2025 10:05:16 +0800</pubDate><description><![CDATA[这就是主要角色类的实例化的顺序过程。分析：Surface的创建过程中，不得不先分析SurfaceControl和Layer的创建，下图是SurfaceControl的创建过程的简化版（详细的代码细节非常多，不便于大家记忆理解，而且太细节容易让大家脑子更糊涂），其中涉及Binder跨进程调用以及JNI调用等。这个在网上很多博客写的还是上面的流程，包括在23、24年的博客，而且用Deepseek等AI去查，结果都是上面的流程，可见AI不是去查最近的源码库，而是基于网上的博客做整理而已。]]></description><category></category></item><item><title><![CDATA[＜span class=“js_title_inner“＞解码60FPS流畅渲染：Android图形子系统核心机制全链路剖析＜/span＞]]></title><link>https://blog.youkuaiyun.com/codeyanbao/article/details/157659120</link><guid>https://blog.youkuaiyun.com/codeyanbao/article/details/157659120</guid><author>codeyanbao</author><pubDate>Thu, 31 Jul 2025 09:15:24 +0800</pubDate><description><![CDATA[测量（Measure）：ViewRootImpl 会触发视图树的测量过程，调用 View 的 measure 方法，确定每个 View 的尺寸。ViewRootImpl 是 Android 视图系统的核心组件，负责连接视图树和窗口系统，处理视图的测量、布局、绘制和输入事件，管理视图的生命周期，以及同步 UI 线程和渲染线程。绘制（Draw）：布局完成后，ViewRootImpl 会触发视图树的绘制过程，调用 View 的 draw 方法，将视图绘制到 Surface 上。]]></description><category></category></item><item><title><![CDATA[解码60FPS流畅渲染：Android图形子系统核心机制全链路剖析]]></title><link>https://blog.youkuaiyun.com/codeyanbao/article/details/149817478</link><guid>https://blog.youkuaiyun.com/codeyanbao/article/details/149817478</guid><author>codeyanbao</author><pubDate>Thu, 31 Jul 2025 09:15:24 +0800</pubDate><description><![CDATA[测量（Measure）：ViewRootImpl 会触发视图树的测量过程，调用 View 的 measure 方法，确定每个 View 的尺寸。ViewRootImpl 是 Android 视图系统的核心组件，负责连接视图树和窗口系统，处理视图的测量、布局、绘制和输入事件，管理视图的生命周期，以及同步 UI 线程和渲染线程。绘制（Draw）：布局完成后，ViewRootImpl 会触发视图树的绘制过程，调用 View 的 draw 方法，将视图绘制到 Surface 上。]]></description><category></category></item><item><title><![CDATA[Unable to select a master clock domain because no path can be found from “SYSTRACE“ to “LINUX_FTRACE]]></title><link>https://blog.youkuaiyun.com/codeyanbao/article/details/123331801</link><guid>https://blog.youkuaiyun.com/codeyanbao/article/details/123331801</guid><author>codeyanbao</author><pubDate>Mon, 07 Mar 2022 15:39:04 +0800</pubDate><description><![CDATA[打开systrace文件报错：Unable to select a master clock domain because no path can be found from “SYSTRACE” to “LINUX_FTRACE_GLOBAL”.
使用systrace生成的trace.html文件无法打开，或者报上面的错误，可以选择下面这个方式：
① 打开谷歌浏览器
② 地址栏输入：chrome://tracing/
③ 点击load按钮，选择要打开的trace.html文件

...]]></description><category></category></item><item><title><![CDATA[Leakcanary原理解析以及换肤框架skin的原理分析]]></title><link>https://blog.youkuaiyun.com/codeyanbao/article/details/121407039</link><guid>https://blog.youkuaiyun.com/codeyanbao/article/details/121407039</guid><author>codeyanbao</author><pubDate>Thu, 18 Nov 2021 18:34:18 +0800</pubDate><description><![CDATA[一、错误现场
 java.lang.ClassCastException: androidx.appcompat.widget.TintContextWrapper cannot be cast to android.app.Activity

 	at leakcanary.internal.navigation.ViewsKt.getActivity(Views.kt:16)

 	at leakcanary.internal.activity.screen.LeaksScreen.onGroupsRe]]></description><category></category></item><item><title><![CDATA[通俗易懂的HashMap源码分析]]></title><link>https://blog.youkuaiyun.com/codeyanbao/article/details/120937495</link><guid>https://blog.youkuaiyun.com/codeyanbao/article/details/120937495</guid><author>codeyanbao</author><pubDate>Sun, 24 Oct 2021 17:55:25 +0800</pubDate><description><![CDATA[据说给我点关注的都成了大佬，点关注的我都会私发一份好东西

前言
HashMap是我们最常用、最常见的一种数据结构。使用起来也非常的方便，主要是通过键值对的方式进行存储，简单明了。
本文将基于Java1.8版本的HashMap源码进行分析，适合Java、Android等初学者以及想了解源码的中高级工程师阅读交流。
① 数据结构
1.1 图示

上图即可简单示意HashMap的整体数据结构，主要是通过数组+链表（满足一定条件时，链表会切换成树）
数组定义为Node类型的数组：
transient Node&.]]></description><category></category></item><item><title><![CDATA[Android dp转px不要再用这么low的方式写了！]]></title><link>https://blog.youkuaiyun.com/codeyanbao/article/details/120580699</link><guid>https://blog.youkuaiyun.com/codeyanbao/article/details/120580699</guid><author>codeyanbao</author><pubDate>Fri, 01 Oct 2021 20:53:30 +0800</pubDate><description><![CDATA[网上一般的答案是这么写的：


public static int dip2px(Context context, float dpValue) {
        final float scale = context.getResources().getDisplayMetrics().density;
        return (int) (dpValue * scale + 0.5f);
}

其实我们仔细想想，我们实际指向对DP的数据做个转换而已，为啥一定要传Context对象，所以其实我们完]]></description><category></category></item><item><title><![CDATA[Java多线程编程(2)之线程同步]]></title><link>https://blog.youkuaiyun.com/codeyanbao/article/details/116379682</link><guid>https://blog.youkuaiyun.com/codeyanbao/article/details/116379682</guid><author>codeyanbao</author><pubDate>Mon, 03 May 2021 19:29:17 +0800</pubDate><description><![CDATA[volatile

	先看个例子

	
class Test {
		// 定义一个全局变量
    private boolean isRun = true;

	  // 从主线程调用发起
    public void process() {
        test();
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStack..]]></description><category></category></item><item><title><![CDATA[Java多线程应用（1）]]></title><link>https://blog.youkuaiyun.com/codeyanbao/article/details/116355306</link><guid>https://blog.youkuaiyun.com/codeyanbao/article/details/116355306</guid><author>codeyanbao</author><pubDate>Sun, 02 May 2021 17:55:52 +0800</pubDate><description><![CDATA[目标：掌握多线程的使用及应用场景



	怎么使用多线程

	
// 尽量不要如此使用
new Thread(new Runnable() {
       @Override
       public void run() {

       }
}).start();
// 通过线程池方便管理
Executor executor = Executors.newCachedThreadPool();
executor.execute(runnable);

	
	
	进程和线程的区别

	其实没有可比.]]></description><category></category></item><item><title><![CDATA[史上最通俗易懂的HTTPS小故事]]></title><link>https://blog.youkuaiyun.com/codeyanbao/article/details/111602456</link><guid>https://blog.youkuaiyun.com/codeyanbao/article/details/111602456</guid><author>codeyanbao</author><pubDate>Wed, 23 Dec 2020 08:13:07 +0800</pubDate><description><![CDATA[序言在绝大部分人的印象中，技术知识都是很枯燥无味的，读起技术文章来，感觉脑细胞都要死一片。今天我们就尝试换一种新的方式，目的是可以让大家在轻松愉快的氛围中还能把技术学了。记得关注我哦，让...]]></description><category></category></item><item><title><![CDATA[通俗易懂的带你了解HTTPS的原理]]></title><link>https://blog.youkuaiyun.com/codeyanbao/article/details/111569150</link><guid>https://blog.youkuaiyun.com/codeyanbao/article/details/111569150</guid><author>codeyanbao</author><pubDate>Tue, 22 Dec 2020 23:08:04 +0800</pubDate><description><![CDATA[序言
在绝大部分人的印象中，技术知识都是很枯燥无味的，读起技术文章来，感觉脑细胞都要死一片。今天我们就尝试换一种新的方式，目的是可以让大家在轻松愉快的氛围中还能把技术学了。记得关注我哦，让我们一起将技术变的有趣起来。
《新编二战回忆录》之HTTPS不讲武德
二战前
二战前夕，德国励精图治，军备急速扩张，收到情报的丘桑立马联系了远在东边的斯大林同志：


由于HTTP协议是明文传输，丘桑和大林同志的微信聊天被元首轻而易举的截获并篡改，以此迷惑住大林同志，元首更加大胆的筹划着下一步动作：闪击波兰
友情提示：看出]]></description><category></category></item><item><title><![CDATA[绝对干货 | Kotlin内联类工作原理及使用案例，看完你会回来谢我的]]></title><link>https://blog.youkuaiyun.com/codeyanbao/article/details/111087699</link><guid>https://blog.youkuaiyun.com/codeyanbao/article/details/111087699</guid><author>codeyanbao</author><pubDate>Sat, 12 Dec 2020 20:30:03 +0800</pubDate><description><![CDATA[初看内联类内联类非常的简单，您只需要在类的前面加上inline关键字就可以：inlineclassWrappedInt(valvalue:Int)
内联类有一些或多或少明显的限制...]]></description><category></category></item><item><title><![CDATA[Kotlin内联类-它是如何工作的以及我们该在什么场景使用它]]></title><link>https://blog.youkuaiyun.com/codeyanbao/article/details/111084434</link><guid>https://blog.youkuaiyun.com/codeyanbao/article/details/111084434</guid><author>codeyanbao</author><pubDate>Sat, 12 Dec 2020 20:18:48 +0800</pubDate><description><![CDATA[初看内联类
内联类非常的简单，您只需要在类的前面加上inline关键字就可以：
inline class WrappedInt(val value: Int)

内联类有一些或多或少明显的限制：需要在主构造函数中精确指定一个属性，如value所示。 您不能在一个内联类中包装多个值。 内联类中也禁止包含init块，并且不能具有带有幕后字段的属性。 内联类可以具有简单的可计算属性，但是我们将在本文后面看到。
在运行时，将尽可能使用内联类的包装类型而不使用其包装。 这类似于Java的框式类型，例如Integer或]]></description><category></category></item></channel></rss>