<?xml version="1.0" encoding="utf-8" ?><rss version="2.0"><channel><title><![CDATA[天亮了的博客]]></title><description><![CDATA[]]></description><link>https://blog.youkuaiyun.com/my_csdnboke</link><language>zh-cn</language><generator>https://blog.youkuaiyun.com/</generator><copyright><![CDATA[Copyright &copy; my_csdnboke]]></copyright><item><title><![CDATA[字节码层面分析 class 类文件结构]]></title><link>https://blog.youkuaiyun.com/my_csdnboke/article/details/115241117</link><guid>https://blog.youkuaiyun.com/my_csdnboke/article/details/115241117</guid><author>my_csdnboke</author><pubDate>Fri, 26 Mar 2021 19:54:27 +0800</pubDate><description><![CDATA[本从字节码层面分析 class 类文件结构。首先来看一道面试题：

java中 String 字符串的长度有限制吗？

平时项目开发中，我们经常会用到 String 来声明字符串，比如 String str = “abc”， 但是你可能从来没有想过等于号之后的字符串常量到底有没有长度限制。要彻底答对这道题，就需要先学会今天所讲的内容——class 文件。
class 的来龙去脉
Java 能够实现"一次编译，到处运行”，这其中 class 文件要占大部分功劳。为了让 Java 语言具有良好的跨平台能力，Ja]]></description><category></category></item><item><title><![CDATA[GC 回收机制与分代回收策略]]></title><link>https://blog.youkuaiyun.com/my_csdnboke/article/details/115210528</link><guid>https://blog.youkuaiyun.com/my_csdnboke/article/details/115210528</guid><author>my_csdnboke</author><pubDate>Thu, 25 Mar 2021 17:49:59 +0800</pubDate><description><![CDATA[垃圾回收（Garbage Collection，简写为 GC）可能是虚拟机众多知识点中最为大众所熟知的一个了，也是Java开发者最关注的一块知识点。Java 语言开发者比 C 语言开发者幸福的地方就在于，我们不需要手动释放对象的内存，JVM 中的垃圾回收器（Garbage Collector）会为我们自动回收。但是这种幸福是有代价的：一旦这种自动化机制出错，我们又不得不去深入理解 GC 回收机制，甚至需要对这些“自动化”的技术实施必要的监控和调节。
前面介绍了 Java 内存运行时区域的各个部分，其中程序计]]></description><category></category></item><item><title><![CDATA[程序运行时，内存到底是如何进行分配的？]]></title><link>https://blog.youkuaiyun.com/my_csdnboke/article/details/115165149</link><guid>https://blog.youkuaiyun.com/my_csdnboke/article/details/115165149</guid><author>my_csdnboke</author><pubDate>Wed, 24 Mar 2021 10:45:13 +0800</pubDate><description><![CDATA[有很多人将 Java 的内存分为堆内存（heap）和栈内存（Stack），这种划分方式在一定程度上体现了这两块区域是 Java 工程师最关注的内存区域。但是其实这种划分方式并不完全准确。
Java 的内存区域划分实际上远比这复杂：Java 虚拟机在执行 Java 程序的过程中，会把它所管理的内存划分为不同的数据区域。下面这张图描述了一个 HelloWorld.java 文件被 JVM 加载到内存中的过程：


HelloWorld.java 文件首先需要经过编译器编译，生成 HelloWorld.class]]></description><category></category></item><item><title><![CDATA[Linux中传统的IPC机制]]></title><link>https://blog.youkuaiyun.com/my_csdnboke/article/details/114013494</link><guid>https://blog.youkuaiyun.com/my_csdnboke/article/details/114013494</guid><author>my_csdnboke</author><pubDate>Wed, 24 Feb 2021 11:00:20 +0800</pubDate><description><![CDATA[介绍
IPC全称为Inter-Process Communication，含义为进程间通信，是指两个进程之间进行数据交换的过程。IPC不是Android中所独有的，任何一个操作系统都需要有相应的IPC机制，比如Windows上可以通过剪贴板等进行进程间通信；Linux上可以通过管道(Pipe)、信号(Sinal)、信号量(Semophore)、消息队列(Message)、共享内存(Share Memory)和套接字(Socket)等来进行进程间的通信。可以看到不同的操作系统有着不同IPC机制，对于Andro]]></description><category></category></item><item><title><![CDATA[GitHub图片加载异常以及README.md添加图片异常]]></title><link>https://blog.youkuaiyun.com/my_csdnboke/article/details/109837195</link><guid>https://blog.youkuaiyun.com/my_csdnboke/article/details/109837195</guid><author>my_csdnboke</author><pubDate>Fri, 20 Nov 2020 09:50:59 +0800</pubDate><description><![CDATA[这些问题是由于 github 的一些域名的 DNS 解析被污染，导致 DNS 解析过程无法通过域名取得正确的 IP 地址。解决方案如下：
https://www.bilibili.com/video/BV1CD4y197tj?from=search&amp;seid=1671507888412118222
笔者是参考了视频中的解决方案。
再总结一下就是：将如下代码拷贝添加到host文件中
windows host 路径：C:\Windows\System32\drivers\etc\host
需要拷贝的代码]]></description><category></category></item><item><title><![CDATA[Android LiveData(二)：源码分析]]></title><link>https://blog.youkuaiyun.com/my_csdnboke/article/details/109740744</link><guid>https://blog.youkuaiyun.com/my_csdnboke/article/details/109740744</guid><author>my_csdnboke</author><pubDate>Tue, 17 Nov 2020 13:38:09 +0800</pubDate><description><![CDATA[Android LiveData(二)：源码分析
有上文对LiveData的基本认识，接下来直接进入LiveData的源码分析，首先进入observer方法，需要注意的是MainActivity继承AppCompatActivity，是LifecycleOwner接口实现类的子孙。而调用observer方法时传入当前MainActivity的上下文，可以理解为owner就是当前的MainActivity。
public void observe(@NonNull LifecycleOwner owner, ]]></description><category></category></item><item><title><![CDATA[Android LiveData(一)：介绍和简单使用]]></title><link>https://blog.youkuaiyun.com/my_csdnboke/article/details/109739764</link><guid>https://blog.youkuaiyun.com/my_csdnboke/article/details/109739764</guid><author>my_csdnboke</author><pubDate>Tue, 17 Nov 2020 11:55:12 +0800</pubDate><description><![CDATA[传统的组件间的通信方式有Handler、BroadcastReceiver，Interface、EventBus等等方式实现，他们有自己适合的应用场景，也有各自的弊端。这里介绍新的组件通信同时LiveData，它是一个数据持有类，具有以下特点：

数据可以被观察者订阅
能够感知组件(Fragment、Activity、Service）)的生命周期
组件处于active状态时，会通知观察者有数据更新

对于观察者模式，不妨先看一个自己模仿LiveData写的简单的例子，数据持有类：
public class ]]></description><category></category></item><item><title><![CDATA[Handler之消息屏障你应该知道的]]></title><link>https://blog.youkuaiyun.com/my_csdnboke/article/details/109531168</link><guid>https://blog.youkuaiyun.com/my_csdnboke/article/details/109531168</guid><author>my_csdnboke</author><pubDate>Fri, 06 Nov 2020 14:37:22 +0800</pubDate><description><![CDATA[前言
由于Handler消息机制的同步屏障问题使用的场景不多，即使不了解可能也不会影响正常开发，因此往往容易被忽视，笔者也是自认比较熟悉Handler的消息机制，在之前同步屏障也算盲区，要想更全面的掌握Handler消息机制，同步屏障就不应该缺席。本文将从同步屏障的插入、删除、使用场景等角度分析同步屏障的工作原理
消息的分类

Message分为3中：普通消息（同步消息）、屏障消息（同步屏障）和异步消息。我们通常使用的都是普通消息，而屏障消息就是在消息队列中插入一个屏障，在屏障之后的所有普通消息都会被挡着，]]></description><category></category></item><item><title><![CDATA[数据结构与算法：二叉查找树/排序树/搜索树]]></title><link>https://blog.youkuaiyun.com/my_csdnboke/article/details/109296211</link><guid>https://blog.youkuaiyun.com/my_csdnboke/article/details/109296211</guid><author>my_csdnboke</author><pubDate>Mon, 26 Oct 2020 19:10:37 +0800</pubDate><description><![CDATA[二叉树的前序遍历，中序遍历，后续遍历的思想，对其应分别对应的介绍了快速排序、汉诺塔、归并排序。二叉树的增删查操作很普通，时间复杂度与链表并没有太多差别。但当二叉树具备一些特性的时候，则可以利用这些特性实现时间复杂度的降低。
二叉查找树/排序树/搜索树
二叉查找树（也称作二叉排序树，二叉搜索树）具备以下几个的特性：


若左子树不为空，那么左子树上面的所有节点的关键字值都比根节点的关键字值小


若右子树不为空，那么右子树上面的所有节点的关键字值都比根节点的关键字值大


左右子树都为二叉树


没有重复值（]]></description><category></category></item><item><title><![CDATA[数据结构与算法：树及二叉树]]></title><link>https://blog.youkuaiyun.com/my_csdnboke/article/details/109234606</link><guid>https://blog.youkuaiyun.com/my_csdnboke/article/details/109234606</guid><author>my_csdnboke</author><pubDate>Fri, 23 Oct 2020 07:10:40 +0800</pubDate><description><![CDATA[树(Tree)
什么是“树”？再完备的定义，都没有图直观。所以我在图中画了几棵“树”。你来看看，这些“树”都有什么特征？

树满足递归定义的特性。也就是说，如果一个数据结构是树结构，那么剔除掉根结点后，得到的若干个子结构也是树，通常称作子树。
在一棵树中，根据结点之间层次关系的不同，对结点的称呼也有所不同。我们来看下面这棵树，如下图所示:
A 结点是 B 结点和 C 结点的上级，则 A 就是 B 和 C 的父结点，B 和 C 是 A 的子结点。
B 和 C 同时是 A 的“孩子”，则可以称 B 和 C 互为]]></description><category></category></item><item><title><![CDATA[数据结构与算法：递归]]></title><link>https://blog.youkuaiyun.com/my_csdnboke/article/details/109070682</link><guid>https://blog.youkuaiyun.com/my_csdnboke/article/details/109070682</guid><author>my_csdnboke</author><pubDate>Wed, 14 Oct 2020 12:56:47 +0800</pubDate><description><![CDATA[如何理解“递归”？
在数学与计算机科学中，递归 （Recursion)）是指在函数的定义中使用函数自身的方法，直观上来看，就是某个函数自己调用自己。
咱们生活中就有很多用到递归的例子。周末你带着女朋友去电影院看电影，女朋友问你，咱们现在坐在第几排啊？电影院里面太黑了，看不清，没法数，现在你怎么办？递归就开始排上用场了。于是你就问前面一排的人他是第几排，你想只要在他的数字上加一，就知道自己在哪一排了。但是，前面的人也看不清啊，所以他也问他前面的人。就这样一排一排往前问，直到问到第一排的人，说我在第一排，然后再]]></description><category></category></item><item><title><![CDATA[数据结构与算法：栈及其应用]]></title><link>https://blog.youkuaiyun.com/my_csdnboke/article/details/109067988</link><guid>https://blog.youkuaiyun.com/my_csdnboke/article/details/109067988</guid><author>my_csdnboke</author><pubDate>Wed, 14 Oct 2020 10:56:00 +0800</pubDate><description><![CDATA[文章目录栈的介绍栈的基本操作顺序栈链式栈栈在表达式求值中的应用栈的应用案例总结
栈的介绍
栈是一种特殊的线性表。栈与线性表的不同，体现在增和删的操作。具体而言，栈的数据结点必须后进先出。后进的意思是，栈的数据新增操作只能在末端进行，不允许在栈的中间某个结点后新增数据。先出的意思是，栈的数据删除操作也只能在末端进行，不允许在栈的中间某个结点后删除数据。
也就是说，栈的数据新增和删除操作只能在这个线性表的表尾进行，即在线性表的基础上加了限制。如下图所示：

栈的基本操作
如何通过栈这个后进先出的线性表，来实现增]]></description><category></category></item><item><title><![CDATA[数据结构与算法：链表及其应用]]></title><link>https://blog.youkuaiyun.com/my_csdnboke/article/details/109053053</link><guid>https://blog.youkuaiyun.com/my_csdnboke/article/details/109053053</guid><author>my_csdnboke</author><pubDate>Tue, 13 Oct 2020 17:54:55 +0800</pubDate><description><![CDATA[基本介绍
相比数组，链表是一种稍微复杂一点的数据结构。数组和链表都属于线性表，一个是顺序存储结构，一个是链式存储结构，最主要的的差别是底层存储结构。
数组需要一块连续的内存空间来存储，对内存要求较高，如果申请一个100MB大小的数组，当内存中没有连续的、足够大的存储空间时，即使内存剩余空间总和大于100MB，仍然申请失败。
链表恰恰相反，它并不需要一块连续的内存空间，它通过“指针”将一组零散的内存块串联起来使用，所以如果申请的是 100MB 大小的链表，只要剩余内存不小于于100MB根本不会有问题。如果剩余]]></description><category></category></item><item><title><![CDATA[数据结构与算法：冒泡排序、插入排序、选择排序]]></title><link>https://blog.youkuaiyun.com/my_csdnboke/article/details/108956561</link><guid>https://blog.youkuaiyun.com/my_csdnboke/article/details/108956561</guid><author>my_csdnboke</author><pubDate>Wed, 07 Oct 2020 22:14:56 +0800</pubDate><description><![CDATA[排序算法太多了，有很多可能你连名字都没听说过，比如猴子排序、睡眠排序、面条排序等。我只讲众多排序算法中的一小撮，也是最经典的、最常用的：冒泡排序、插入排序、选择排序、归并排序、快速排序、计数排序、基数排序、桶排序。按照时间复杂度把它们分成了三类,本文先分析冒泡、插入、选择三种排序算法




排序算法
时间复杂度
是否基于比较




冒泡、插入、选择
O(n²)
√


快排、归并
O(nlongn)
√


桶、计数、基数
O(n)
×


带着问题去学习，是最有效的学习方法。所以按照惯例，我还是先给你]]></description><category></category></item><item><title><![CDATA[数据结构与算法：数组]]></title><link>https://blog.youkuaiyun.com/my_csdnboke/article/details/108937743</link><guid>https://blog.youkuaiyun.com/my_csdnboke/article/details/108937743</guid><author>my_csdnboke</author><pubDate>Tue, 06 Oct 2020 11:44:56 +0800</pubDate><description><![CDATA[定义
什么是数组？数组（Array）是一种线性表数据结构。它用一组连续的内存空间，来存储一组具有相同类型的数据。先简单介绍一下几个关键词线性表、连续的内存空间
线性表（Linear List），顾名思义，线性表就是数据排成像一条线一样的结构。每个线性表上的数据最多只有前和后两个方向。其实除了数组，链表、队列、栈等也是线性表结构。

而与它相对立的概念是非线性表，比如二叉树、图等。之所以叫非线性，是因为，在非线性表中，数据之间并不是简单的前后关系

连续的内存空间和相同类型的数据,正是因为这两个限制，它才有了]]></description><category></category></item><item><title><![CDATA[数据结构与算法：复杂度分析]]></title><link>https://blog.youkuaiyun.com/my_csdnboke/article/details/108930834</link><guid>https://blog.youkuaiyun.com/my_csdnboke/article/details/108930834</guid><author>my_csdnboke</author><pubDate>Mon, 05 Oct 2020 17:49:52 +0800</pubDate><description><![CDATA[为什么需要复杂度分析？
你可能会有些疑惑，我把代码跑一遍，通过统计、监控，就能得到算法执行的时间和占用的内存大小。为什么还要做时间、空间复杂度分析呢？这种分析方法能比我实实在在跑一遍得到的数据更准确吗？首先，我可以肯定地说，你这种评估算法执行效率的方法是正确的。很多数据结构和算法书籍还给这种方法起了一个名字，叫事后统计法。但是，这种统计方法有非常大的局限性。
1.测试结果非常依赖测试环境
测试环境中硬件的不同会对测试结果有很大的影响。 比如，我们拿同样一段代码，分别用 Intel Core i9 处理器和 ]]></description><category></category></item><item><title><![CDATA[Android组件化实战六：路由架构设计]]></title><link>https://blog.youkuaiyun.com/my_csdnboke/article/details/106954260</link><guid>https://blog.youkuaiyun.com/my_csdnboke/article/details/106954260</guid><author>my_csdnboke</author><pubDate>Thu, 25 Jun 2020 07:29:17 +0800</pubDate><description><![CDATA[前言
结合前面的模块之间的交互，主要分析了类加载、全局Map记录(跳转目标Class)两种交互方式，以及APT和JavaPoet技术生成类文件，本文分析组件化的路由架构，我们到底需要通过APT和JavaPoet生成什么样的类文件呢？
组件化路由架构设计

先来看这样一幅架构设计图，组文件记录是一对一的即一个子模块对应一个组文件记录，而一个组文件记录对应多个路径文件记录，第二点比较好理解，因为各个子模块有多个Activity，对应多个路径信息。对应第一点，为什么要生成一对一的组(名)文件记录呢？试想一下，如果]]></description><category></category></item><item><title><![CDATA[Android组件化实战五: APT的高级用法JavaPoet]]></title><link>https://blog.youkuaiyun.com/my_csdnboke/article/details/106825259</link><guid>https://blog.youkuaiyun.com/my_csdnboke/article/details/106825259</guid><author>my_csdnboke</author><pubDate>Thu, 18 Jun 2020 10:49:15 +0800</pubDate><description><![CDATA[前言
上一篇文章简单介绍了APT及其使用，生成相应的java文件，帮我们执行相关的操作，生成java文件的方式是字符串拼接的方式，但是如果要生成的java文件成员属性和方法比较多，这种方式就比较麻烦了，而且容易出现人为失误。所有就有了API调用的方式生成java文件，也就是JavaPoet。
什么是JavaPoet
项目主页及源码：https://github.com/square/javapoet
APT + JavaPoet = 超级利刃
JavaPoet是square推出的开源java代码生成框架，提]]></description><category></category></item><item><title><![CDATA[Android组件化实战四: APT的介绍与使用]]></title><link>https://blog.youkuaiyun.com/my_csdnboke/article/details/106822616</link><guid>https://blog.youkuaiyun.com/my_csdnboke/article/details/106822616</guid><author>my_csdnboke</author><pubDate>Thu, 18 Jun 2020 08:20:06 +0800</pubDate><description><![CDATA[前言
上一篇文章分析了组件化模块交互的两种实现方式，对于全局Map保存目标Activity的路径信息和类对象方案，如果Activity的数量繁多，则需要在主模块app的application中重复执行多次保存操作，既不优雅，又不符合实际开发场景，我们想到的解决之一就是想办法生成一个来完成这个重复枯燥的任务，生成一个类来帮我们找到跳转目标Activity的class对象。好比Butterknife生成一个文件专门完成findViewById的操作一样。这就涉及到注解处理器即apt技术，接下来就了解apt的使用]]></description><category></category></item><item><title><![CDATA[Android组件化实战三: 模块之间的交互]]></title><link>https://blog.youkuaiyun.com/my_csdnboke/article/details/106720736</link><guid>https://blog.youkuaiyun.com/my_csdnboke/article/details/106720736</guid><author>my_csdnboke</author><pubDate>Fri, 12 Jun 2020 17:40:39 +0800</pubDate><description><![CDATA[前言
上一篇文章记录了组件化开发中的项目部署需要注意的地方，而本文旨在实现模块之间的交互，比如页面的跳转，数据的传递等等，而在集成化模式下，各个子模块都是library，到底该如何实现呢？首先我们要知道传统的组件间的通信方式，以及其适用场景和优缺点。
组件间通信的传统方式

EventBus：不同的消息需要定义不同的EventBean(一对一)，导致EventBean会非常多，而且一对多就会混乱、难以维护
反射：反射技术可以实现，维护成本高且容易出现高版本@hide限制
隐式意图：维护成本还好，只是比较麻烦]]></description><category></category></item></channel></rss>