<?xml version="1.0" encoding="utf-8" ?><rss version="2.0"><channel><title><![CDATA[ZH的博客]]></title><description><![CDATA[路漫漫其修远兮，吾将上下而求索。]]></description><link>https://blog.youkuaiyun.com/m0_69650487</link><language>zh-cn</language><generator>https://blog.youkuaiyun.com/</generator><copyright><![CDATA[Copyright &copy; m0_69650487]]></copyright><item><title><![CDATA[Kotlin协程基础]]></title><link>https://blog.youkuaiyun.com/m0_69650487/article/details/144917973</link><guid>https://blog.youkuaiyun.com/m0_69650487/article/details/144917973</guid><author>m0_69650487</author><pubDate>Sun, 05 Jul 2026 20:08:06 +0800</pubDate><description><![CDATA[Kotlin协程是用JVM线程实现的，并没有改变线程的本质。它所提供的API也都可以使用线程的方式进行实现。但是实际开发中，通常来说没有时间和精力，或者有这个水平来做高性能的并发优化。Kotlin帮助我们做了优化，只需要使用它提供的API就能实现高效的并发编程。协程用更加直观的代码结构，做到了线程方式需要用复杂的回调才能做到的事，这就是Kotlin协程真正的优势。]]></description><category></category></item><item><title><![CDATA[Kotlin函数]]></title><link>https://blog.youkuaiyun.com/m0_69650487/article/details/145592745</link><guid>https://blog.youkuaiyun.com/m0_69650487/article/details/145592745</guid><author>m0_69650487</author><pubDate>Sun, 05 Jul 2026 20:07:42 +0800</pubDate><description><![CDATA[在Kotlin中object是一个关键词，使用它修饰一个类，替换掉class关键字，表示创建一个类，并创建一个这个类的对象，实际上就是一个单例。它的原理就是这个参数除了被当做函数参数之外，Kotlin还会帮我们在类里自动创建一个和参数同名的属性，并把这个参数的值作为属性的初始值。这样写的属性和函数，不属于任何class而是属于package，它跟静态变量和方法一样，是全局的，而且用起来更加方便，连类名都不需要写，直接用就可以。lambda也是函数类型对象，它和匿名函数是同样的用法，可以理解为是同样的东西。]]></description><category></category></item><item><title><![CDATA[Translation & MotionLayout]]></title><link>https://blog.youkuaiyun.com/m0_69650487/article/details/144435172</link><guid>https://blog.youkuaiyun.com/m0_69650487/article/details/144435172</guid><author>m0_69650487</author><pubDate>Sun, 05 Jul 2026 20:07:05 +0800</pubDate><description><![CDATA[被接管的布局，即是当前展示的布局。1、<OnClick>标签描述点击事件，其中targetId属性指定点击事件作用在哪个控件，clickAction属性定义点击时要执行的操作，常用的toggle值，表示当前处于开始状态，请将动画效果切换为结束状态；当然这里举的是简单的属性动画例子，实际上像缩放、平移、旋转等都可以用过渡动画实现，只需要指定修改的属性，不需要像属性动画那样，计算变化的高度、宽度、距离、角度等。可以传递整个xml文件，分别传递开始场景和结束场景的布局文件，就可以实现两个布局切换的过渡动画。]]></description><category></category></item><item><title><![CDATA[Drawable和Bitmap的区别]]></title><link>https://blog.youkuaiyun.com/m0_69650487/article/details/144297137</link><guid>https://blog.youkuaiyun.com/m0_69650487/article/details/144297137</guid><author>m0_69650487</author><pubDate>Sun, 05 Jul 2026 20:06:49 +0800</pubDate><description><![CDATA[b、否则，先创建一个bitmap，给drawable设置边界范围（调用drawable的draw方法前，需要设置范围，不设置的话默认是空的范围），调用draw方法，把像素绘制到bitmap上，最后将bitmap返回。Drawable的绘制，是在draw方法里，执行绘制的代码。我们在绘制复杂view时，可以将绘制工作进行拆解，搬到drawable里面，降低绘制的复杂度，也方便对于需要重复绘制的部分进行重用。Bitmap是图象像素信息的存储工具，而Drawable是绘制的代码，表达的是绘制规则。]]></description><category></category></item><item><title><![CDATA[Java泛型详解]]></title><link>https://blog.youkuaiyun.com/m0_69650487/article/details/144223151</link><guid>https://blog.youkuaiyun.com/m0_69650487/article/details/144223151</guid><author>m0_69650487</author><pubDate>Sun, 05 Jul 2026 20:06:34 +0800</pubDate><description><![CDATA[通过字段、方法的反射方法：field.getGenericType()、method.getGenericRenturType()、method.getGenericParameterTypes()可以分别获取字段的泛型类型、方法的泛型返回值类型、方法的泛型参数类型。这样再调用就没有问题。extends”限定符，它的作用是放宽声明变量时的要求，让子类类型的泛型对象可以赋值给父类类型泛型的引用。泛型从本质上来说，是做一个通用的功能，可以锁定类型，但是现在先不锁定，等到实例化它的时候在进行类型的确认锁定。]]></description><category></category></item><item><title><![CDATA[Rxjava]]></title><link>https://blog.youkuaiyun.com/m0_69650487/article/details/141036666</link><guid>https://blog.youkuaiyun.com/m0_69650487/article/details/141036666</guid><author>m0_69650487</author><pubDate>Sat, 04 Jul 2026 09:16:53 +0800</pubDate><description><![CDATA[Rxjava有非常多的操作，我们只解析主要的几个：create、map、subscribe，以及切换线程的subscribeOn和observeOn方法的实现原理。让我们通过对RxJava的使用以及对框架的解析，理解这种不同于以往的编程思想。响应式编程是一种编程思想，一个起点和一个终点，事件从起点开始，中间有多个拦截，对事件进行处理，最终事件会流向终点，被终点消费掉。ObservableMap的内部类MapObserver的onNext方法，会回调我们重写的apply方法，完成数据变化。]]></description><category></category></item><item><title><![CDATA[APP启动优化]]></title><link>https://blog.youkuaiyun.com/m0_69650487/article/details/141036831</link><guid>https://blog.youkuaiyun.com/m0_69650487/article/details/141036831</guid><author>m0_69650487</author><pubDate>Sat, 04 Jul 2026 09:15:07 +0800</pubDate><description><![CDATA[向上表示调用的层次，即下方的方法，调用执行上面的方法，因此图形越像上越窄，看上去像火焰的形状，因而也被称为“火焰图”。将这些任务同时启动起来，闭锁计数为0的可以直接执行，当执行完成后，将被它所依赖的任务的闭锁计数减1，当一个任务的闭锁计数为0就可以自动执行起来，如此往复循环。因为这里是采用inflate的方式，解析布局文件，并利用反射来创建View，这个过程是十分耗时的。这个图示，实际上是一个调用顺序表，最上面的最顶层的函数，向下是它调用的方法，这个表会统计每个函数执行的时间，执行占用百分比等。]]></description><category></category></item><item><title><![CDATA[APK瘦身]]></title><link>https://blog.youkuaiyun.com/m0_69650487/article/details/141036498</link><guid>https://blog.youkuaiyun.com/m0_69650487/article/details/141036498</guid><author>m0_69650487</author><pubDate>Sat, 04 Jul 2026 09:13:39 +0800</pubDate><description><![CDATA[应用安装包过大会导致应用的安装、启动耗时增加，也会导致应用在使用时占用的内存大以及产生耗电问题。本文介绍应用安装包的结构，以及常用的包体积优化方法及原理。]]></description><category></category></item><item><title><![CDATA[Android Gesture Detector工具]]></title><link>https://blog.youkuaiyun.com/m0_69650487/article/details/140936988</link><guid>https://blog.youkuaiyun.com/m0_69650487/article/details/140936988</guid><author>m0_69650487</author><pubDate>Sat, 04 Jul 2026 09:11:47 +0800</pubDate><description><![CDATA[我们知道Android中的事件，实际是一个事件序列，由一个Down事件、若干个Move事件，以及一个Up或Cancel事件组成。我们之所以能够区别长按、单击、双击、滑动等，都是通过对这个事件序列进行解析之后得到的。如Down事件之后500ms之内抬起（Up事件），则解析为单击；Down事件之后超过500ms抬起，触发长按。这种将事件序列解析为具体的行为的工作就是手势侦测。]]></description><category></category></item><item><title><![CDATA[图形工具Xfermode介绍]]></title><link>https://blog.youkuaiyun.com/m0_69650487/article/details/140937389</link><guid>https://blog.youkuaiyun.com/m0_69650487/article/details/140937389</guid><author>m0_69650487</author><pubDate>Sat, 04 Jul 2026 09:11:10 +0800</pubDate><description><![CDATA[Xfermode是用于两张图片进行融合的技术。它实际上应该是transfermode，因为一些美国人习惯省事把“trans”读作“X”。它实际上是Paint类一个方法的参数，指定接下来按照融合的方式进行绘制。setXfermode这个方法的参数本来有三种，其余两种已经被遗弃的状态，现在只剩下一种，就是PorterDuffXfermode。它是用发明它的两个人的名字Porter和Duff定义的名称。PorterDuffXfermode提供15中融合方式。原图和目标图：2、将方形图片绘制成圆形。]]></description><category></category></item><item><title><![CDATA[约束布局详解]]></title><link>https://blog.youkuaiyun.com/m0_69650487/article/details/140725482</link><guid>https://blog.youkuaiyun.com/m0_69650487/article/details/140725482</guid><author>m0_69650487</author><pubDate>Fri, 03 Jul 2026 19:17:20 +0800</pubDate><description><![CDATA[布局优化是我们在开发中常常遇到的问题。我们知道布局越复杂嵌套层次越深则加载它的开销越大，性能越差。约束布局是我们在进行布局优化时经常会考虑使用的方式。约束布局不仅提供了一些如百分比布局、角度定位、辅助线等一些好用的工具，帮助我们可以轻松实现一些效果。最主要的是，它使得布局扁平化，减少了布局的层次，从而提升了加载布局的效率。]]></description><category></category></item><item><title><![CDATA[Android Handler机制]]></title><link>https://blog.youkuaiyun.com/m0_69650487/article/details/140725136</link><guid>https://blog.youkuaiyun.com/m0_69650487/article/details/140725136</guid><author>m0_69650487</author><pubDate>Fri, 03 Jul 2026 19:14:47 +0800</pubDate><description><![CDATA[主线程是不可以退出的。上面我们对于Handler原理的分析，知道在MessageQueue中没有消息在处理的时候，会调用底层的方法进入沉睡状态。之所以我们应用程序能够一直存在，主要是因为在Looper.loop函数里面会执行一个无限的for循环，周而复始的处理消息，让Android程序持续存活并完成各种功能。通常上层在调用postSyncBarrier，会开始插入异步消息，插入异步消息的方法，就是插入一个普通消息，调用这个消息的setAsynchronous(true)将它变成一个异步消息。]]></description><category></category></item><item><title><![CDATA[Activity启动模式]]></title><link>https://blog.youkuaiyun.com/m0_69650487/article/details/140724876</link><guid>https://blog.youkuaiyun.com/m0_69650487/article/details/140724876</guid><author>m0_69650487</author><pubDate>Fri, 03 Jul 2026 19:13:21 +0800</pubDate><description><![CDATA[Activity的四种启动模式，主要围绕任务启动和任务切换的问题，目的是为了更加精准的可控的界面导航。SingleTop 和 Standard定义的是在当前栈打开的行为。而singleTask和singleInstance则是定义跨Task打开的行为，展现跨Task交互的意图。实际使用上，standard和singleTop多在app内部使用；singleInstance比较多用于定义给开放出来给其他app共享使用的activity；SingleTask内部交互和外部共享都适用。]]></description><category></category></item><item><title><![CDATA[View触摸反馈与事件分发原理]]></title><link>https://blog.youkuaiyun.com/m0_69650487/article/details/132767843</link><guid>https://blog.youkuaiyun.com/m0_69650487/article/details/132767843</guid><author>m0_69650487</author><pubDate>Fri, 03 Jul 2026 19:12:02 +0800</pubDate><description><![CDATA[如果子View不消费，则传递到它下层的子View，继续做同样的判断，如果所有子view都不消费。View的原生事件处理主要做几件事情，结合手指的按下、移动、抬起一系列的动作，进行“点击”、“长按”、“显示TOOLTIP”，以及“是否进行滑动”的检查。我们看到上面进行事件拦截判断时，当MOVE事件过来，已经有子view处理在处理该事件序列时，可以通过设置FLAG_DISALLOW_INTERCEPT允许父view拦截，然后父view的onIntercepTouchEvent()方法返回true。]]></description><category></category></item><item><title><![CDATA[自定义View之文字测量原理与文字特效实现]]></title><link>https://blog.youkuaiyun.com/m0_69650487/article/details/132767752</link><guid>https://blog.youkuaiyun.com/m0_69650487/article/details/132767752</guid><author>m0_69650487</author><pubDate>Fri, 03 Jul 2026 19:00:30 +0800</pubDate><description><![CDATA[本文详细介绍了Android自定义View中文字绘制的关键技术与常见问题解决方案。首先解析了文字测量原理，包括baseline、ascent/descent等概念，解决了文字居中和贴边显示不准确的问题。然后讲解了多行文字绘制方法，包括使用StaticLayout和自定义换行逻辑。最后以歌词效果为例，演示了文字渐变效果的实现原理——通过分层绘制和剪裁控制。文章提供了文字贴边、垂直居中、动态换行等实用技巧，并附有实现思路和效果图示，帮助开发者掌握精细化文字绘制技术。文末还提供了文字绘制知识体系的思维导图参考。]]></description><category></category></item><item><title><![CDATA[NestedScrollView实现嵌套滑动机制]]></title><link>https://blog.youkuaiyun.com/m0_69650487/article/details/142572025</link><guid>https://blog.youkuaiyun.com/m0_69650487/article/details/142572025</guid><author>m0_69650487</author><pubDate>Thu, 26 Sep 2024 19:35:52 +0800</pubDate><description><![CDATA[本文介绍一种常用的实现嵌套滑动的开源框架NestedScrollView。通过它可以优雅的实现嵌套滑动的效果。]]></description><category></category></item><item><title><![CDATA[属性动画与硬件加速]]></title><link>https://blog.youkuaiyun.com/m0_69650487/article/details/132767618</link><guid>https://blog.youkuaiyun.com/m0_69650487/article/details/132767618</guid><author>m0_69650487</author><pubDate>Sun, 23 Jun 2024 21:43:26 +0800</pubDate><description><![CDATA[在屏幕显示的时候，GPU拿着cpu的指令，直接转换为像素应用到屏幕上，显示文字，图形等元素。本文根据动画常见的使用场景，详细总结一下Android中各种属性动画的区别和特点，以及制作复杂动画所用到的关键帧、插值器、估值器的原理、使用场景和方法。view的绘制是非常频繁的操作。为了性能考虑，android每次绘制信号到来（就是我们常说的VSync信号），并不会整个界面，只绘制改变了的区域。它的主要原理是，这些view自带的属性，被android做了优化，这些属性的改变，不会导致gpu操作的改变。]]></description><category></category></item><item><title><![CDATA[Grdle构建原理分析]]></title><link>https://blog.youkuaiyun.com/m0_69650487/article/details/132767480</link><guid>https://blog.youkuaiyun.com/m0_69650487/article/details/132767480</guid><author>m0_69650487</author><pubDate>Sun, 23 Jun 2024 21:40:21 +0800</pubDate><description><![CDATA[它的作用是包住gradle，实际上做工作的是它里面的gradle。java语言提供匿名内部类和lamda表达式的形式来传递方法，它实际上传递的是类的对象，而不是方法本身。前面说的buildType flavorDimensions生成的变体，实际上是通过插件根据配置创建出不同的task（后面准备分享一票Android apk编译打包的过程，这里再详细进行介绍）。事实上，老的版本Gradle只提供compile方法，新的版本提供了非传递依赖的implementation方法和传递依赖的api方法。]]></description><category></category></item><item><title><![CDATA[（三）OkHttp网络请求拦截器详解]]></title><link>https://blog.youkuaiyun.com/m0_69650487/article/details/132112546</link><guid>https://blog.youkuaiyun.com/m0_69650487/article/details/132112546</guid><author>m0_69650487</author><pubDate>Sun, 06 Aug 2023 08:54:05 +0800</pubDate><description><![CDATA[这个拦截器一般做网络调试用，用户自定义，插在连接拦截器和请求服务拦截器之间。整个OkHttp的网络请求工作都是在这个五大拦截器中完成。他们分别负责不同的工作，如果流水线一样，经过五到工序，最终完成了完整的工作。]]></description><category></category></item><item><title><![CDATA[（二）OkHttp网络请求配置参数详解]]></title><link>https://blog.youkuaiyun.com/m0_69650487/article/details/132112365</link><guid>https://blog.youkuaiyun.com/m0_69650487/article/details/132112365</guid><author>m0_69650487</author><pubDate>Sun, 06 Aug 2023 08:50:03 +0800</pubDate><description><![CDATA[前面说到OkHttp网络请求的总体框架。这一章节主要通过解读OkHttpClient的内容，了解可以通过框架配置哪些参数，以及这些参数的意义。让我们对OkHttp框架和HTTP协议之间的关系有更深的了解。]]></description><category></category></item></channel></rss>