光明顶的熊 - Android 基础
type: channel
link: https://blog.smallraw.com/category/AndroidBasic/
description: Android 那些跨不过去的门槛 ，以前欠下的账早晚是要还的
items: Apple Silicon Room Database 临时使用方案
items: Android 操作系统&内核概念扫盲
items: 速查 | Android 系统目录功能
items: 我没有 Root 的手机，我又想看相关目录怎么办
items: ConstraintLayout 效率爆表的技巧
items: ConstraintLayout 实战经验
items: ConstraintLayout 炫酷的动画
items: 最强大的布局 ConstraintLayout
items: Android开发需要了解的网络协议
items: Android 的 ClassLoader

Apple Silicon Room Database 临时使用方案
type: item
date: 2021-01-03T15:44:00+08:00
description: 截止发稿时 Room 的最新版本为 2.3.0-alpha04，这个版本无法在 Apple Silicon 中使用。看了一下 Room 的 Sqlite Jdbc 版本为 3.25.2。然后查看了一下 Sqlite Jdbc Releases 他是在 3.32.3.3 版本中开始兼容 Apple Silicon M1 芯片的。我们可以自己单独引用 Jdbc，只要引用的版本高于 3.32.3.3 即可解决这个问题。implementation("androidx.room:room-runtime:2.3.0-alpha04") { exclude(group:'org.xerial') } kapt("androidx.room:room-compiler:2.3.0-alpha04"){ exclude(group:'org.xerial') } implementation("androidx.room:room-ktx:2.3.0-alpha04"){ exclude(group:'org.xerial') } implementation 'org.xerial:sqlite-jdbc:3.34.0'

Android 操作系统&内核概念扫盲
type: item
date: 2020-07-12T23:55:00+08:00
description: 名词解释内核（Kernel）：管理硬件资源，向应用程序提供所需的硬件资源。系统调用：是内核提供的应用程序与内核的沟通桥梁。POSIX（Portable Operating System Interface of UNIX）：是操作系统提供的应用程序与操作系统的沟通桥梁。它是统一的标准许多系统都支持。C 标准库：因为操作系统的使用的库通常是用 C 语言提供的。所以 C 标准库是封装了很多方便我们系统或应用程序开发的函数，当然其中也包含对 系统调用 的封装。守护进程：他是在系统里运行的后台任务，此类程序会被以进程的形式初始化。不会接受用户的直接操作。ELF 文件：(Executable and Linkable Format)是一种用于可执行文件、目标文件、共享库和核心转储的标准文件格式。目前常见的 Linux、 Android 可执行文件、共享库（.so）、目标文件（ .o）以及 Core Dump 文件均为此格式。Android 官方网站的 Android 系统结构图首先最底层是内核内核主要作用是管理硬件，也要保障安全等功能。所以其中包含硬件的驱动，以及硬件的工作方式和模型。比如：给 CPU 定义出进程，线程等任务调度的工作逻辑。内存的工作方式等。HAL 安卓独有的一层提供了一层标准的 API ，这样底层硬件如何变化上层将不再关心。这一层相当于充当适配的一层，隔离开上下层的变化。Native C/C++ 库层其中各种第三方库的 ELF 可执行文件，包含守护进程，C 标准库，空的 Android 应用进程。Android 引入了很多功能的 ELF 可执行文件，然后通过守护进程的方式运行起来。比如 Wi-Fi 功能的可执行文件，蓝牙的可执行文件等等，最后都是以守护进程的方式在后台运行的。这一层干的事比较多可以分为二层，首先这第一层提供的 C 标准库和 Android 系统需要用到的很多 Linux 和独有的守护进程和各种第三方库的 ELF 可执行文件。比如系统可能需要联网功能的守护进程，通信守护进程，GPS 守护进程，声音守护进程等等，这里可以根据系统功能进行精简或添加。Android 用了很多第三方的库和手段来保持 Android 系统正常和稳定的运行和应用的可执行性，到这一层为止基本上 Google 已经提供了一套没有 UI 环境的低功耗版 Linux 系统的方案，使其可以运行在各种微型或小型设备上。基本的低功耗 Linux 系统已经有了，剩下的就可以根据自己的想法来定义系统生态和玩法了。Android 的玩法是想使用 Java 语言作为应用开发语言，所以 Android 需要提供一套 JVM 虚拟机和一些基础服务。所以 Android 又垒了第二层 Android 使用原生代码实现了 Android 的运行时（Android Runtime）。Android Runtime 中包含了 Android 应用程序运行的基本库、基础服务和一台 JVM 虚拟机来运行 Java。Java 库Google 的玩法是在该层通过 Java 语言编写了 Android OS 的系统的基础功能的 API 、服务和各项可视化的系统功能。比如为了统一应用开发标准，定义基本的 Android 应用运行逻辑，抽象出了四大组件供开发者快速开发。以及系统运行的各项基础服务，底层的通信，GPS，摄像头等等守护进程的 Java 封装。然后在之上又做了一些系统级的应用界面。应用层使用 SDK 和 C 标准库开发的应用，每个应用其实都是一个或多个 Android Runtime 的实例进程，把 Java 的代码在虚拟机中运行。个人理解的 Android 操作系统官方 Android 源码结构图

速查 | Android 系统目录功能
type: item
date: 2020-07-11T00:45:00+08:00
description: root 文件系统目录或文件功能解释acctacct cgroup（control group）的挂载点apexAndroid 10 模块化了一些Android系统组件，使其能在 Android 大版本升级之外进行独立升级，即系统组件模块化（Modular System Components）。这些模块化的系统组件打包到一起，可以通过 OTA 方式推送给终端用户进行升级。cache缓存的大小被限制为这个分区的大小。d/sys/kernel/debug 的一个符号链接。data存放用户安装的软件以及各种数据。default.prop其中记录的是编译时 /build/core/main.mk 中 ADDITIONAL_DEFAULT_PROPERTIES 变量中的值， init 将根据它（的内容）去加载其他系统范围内的属性文件（property）。加载只读的属性文件有利于强制执行安全保护devtmpfs 文件系统的挂载点，定义了应用程序可用的设备。/dev/cpuctl 目录是 cpuctl 控制组的挂载点，使用 cgroup 伪文件系统。etc/system/etc 的一个符号链接。与 Linux 功能一致，存放配置文件init处理 init.rc 文件的一个二进制程序。init.rc 文件引入其他 init.*.rc 文件。Android 启动时，内核会在启动进程的最后运行 init 程序。init.rc 文件值得一读，它告诉我们一些 Android 设备配置的事情。由于 Android 不支持 /etc/sysctl.conf，所以 /proc/sys/kernel 参数的更新就成为了 init.rc 文件的一部分。除非你对 Linux 内核的内部工作机制有一个好的理解，最好不要修改这些参数。对 /dev/cpuctl 的参数也是一样的道理。mnt除了挂载内部和外部SD卡，这个目录还是其他文件系统的挂载点。/mnt/asec 目录是一个 tmpfs 文件系统的挂载点，它是 Android 安全机制的一部分。/mnt/obb 目录是一个 tmpfs 文件系统的挂载点，它用来存储应用程序文件超出 50MB 后的扩展文件。/mnt/secure 目录是 Android 安全机制的另外一个组件。你也可以看到一个或多个 USB 设备的挂载点。procprocfs 文件系统的挂载点，用来提供对内核数据结构的访问。sbin比标准 Linux 发行版中的 /sbin 目录小很多，但它确实包含了几个重要守护进程的二进制文件。sdcard/mnt/sdcard 的一个符号链接。storage外部SD卡所在目录syssysfs 伪文件系统的挂载点，sysfs 伪文件系统是内核的设备对象结构的反映。这个目录下有很多信息，但它需要理解内核设备模型。简而言之，这些目录表示内核对象，而文件是这些对象的属性。system这个目录下就是你通常在标准 Linux 发行版中 root 目录下看到的目录。这些目录包括 bin、etc、lib、usr和xbin。ueventd.rc这些文件定义了/dev目录的配置规则。vendor/system/vendor 的一个符号链接。init.rc系统初始化脚本。同样里面会引用 init.*.rc 文件。/system 文件系统存放所有谷歌或厂商提供的 Android 组件的地方，该文件系统是以只读方式 mount 的，主要是考虑了稳定性和安全性。目录或文件功能解释app存放系统应用，一般是系统或厂商自带应用。apexAndroid 10 模块化了一些Android系统组件，使其能在 Android 大版本升级之外进行独立升级，即系统组件模块化（Modular System Components）。这些模块化的系统组件打包到一起，可以通过 OTA 方式推送给终端用户进行升级。bin存放二进制可执行文件 ： 其中既有多个守护进程的二进制可执行文件，也有一些命令行 shell 的二进制可执行文件。一般是系统自带的。（大多数指向 looIbox)etc各种系统组件的配置文件fonts存放各种字体文件framework存放 Android 的框架（framework ） ， 各个 framework 会被存放在各自对应的 .jar 文件中lib存放运行时库文件，也就是原生的 .so (ELF shared object），在 Android 中，这个目录扮演了和正常 Linux 系统中的 /lib 目录一样的角色。media存放铃声、系统提示声的文件夹。xbin存放用途特殊的、正常操作过程不需要使用的二进制文件，一般是系统管理工具。build.prop编译过程中生成的属性配置文件。priv-app存放特权的 Appusr支持文件，比…

我没有 Root 的手机，我又想看相关目录怎么办
type: item
date: 2020-07-09T11:17:00+08:00
description: 标签: Android 开发小技巧如题目，我没有拥有 Root 权限的 Android 手机，我又想看 Android 系统的相关目录怎么办？今天我们用 Android Studio 自带的虚拟机来解决一下这个问题。因为 Windows，Mac 等等的可能快捷键不一样或者因为 Android Studio 版本的问题按钮位置或图标不一样。知道怎么能够快捷打开就不用看我啰嗦了。所以下文讲的操作方式无论在哪个版本和平台上都一样的。本文将介绍，如何拥有一个 Root 的系统环境，以为学习 Android 系统、App 调优等等需求做铺垫。创建虚拟机管理器在 Android Studio 页面按两下 Shift 键，输入 avd manager ，如果有多个选项，注意是选 Actions 这一栏下面的 AVD Manager，打开虚拟机管理器。然后创建一个新的虚拟机。然后外观你可以随便选，然后点击 Next。这一步很关键了，我们不要使用推荐的镜像，首先将选项卡切到 X86 镜像。这里我们要选择的是右边名称中没有（Google APIs）字样的系统镜像，如果不能选就需要点击左边 Download 先下载。下载完成镜像后选择下载的镜像，直接点击 Next。同样这一步如果没有特殊需求不建议做修改，直接点击 Finish 完成。这样我们的虚拟机就创建完毕了。如果想打开虚拟机，直接在虚拟机管理点三角打开即可。查看虚拟机文件你可能会因为操作系统版本或 Android Studio 版本问题找不到这个功能，所以以下展示通用开启方式，如果你知道怎么打开直接打开就可以。前提是你先打开了虚拟机。同样我们按两下 Shift 键，输入 device file explorer ,如果有多个选项，注意是选 Actions 这一栏下面前面带图标的 Device File Explorer ，打开该功能。如图，每个文件夹都有不同的功能和作用，具体详情请看我的博客 Android 系统目录功能速查。ADB 带 Root 权限的调试如果自己配置过 ADB 环境，你想使用系统的终端或 CMD 命令窗都是可以的，这里使用通用方案。在 Android Studio 页面按两下 Shift 键，输入 terminal ，如果有多个选项，注意是选 Actions 这一栏下面前面带图标的的 Terminal，打开 Android Studio 的终端。如果你是第一次打开并使用你新创建的虚拟机，那么你先要输入一句 adb root 命令，来开启 ADB 的 Root 权限。然后输入 adb shell 就可以进入手机调试了。如何区分你进入的 ADB shell 是不是 Root 权限，你先输入 adb shell 命令打开调试，你看终端显示的符号，如果是 $ 就不是 Root 环境，如果显示 # 就是 Root 环境了。接下来你就能够使用带 Root 权限的 ADB 命令了。比如我们可以进入 /proc 文件夹看各项服务的进程状况。更多 ADB 用法 ADB 用法大全

ConstraintLayout 效率爆表的技巧
type: item
date: 2018-10-18T22:48:00+08:00
description: 这是一篇极短的技巧文，但是能解决你使用 ConstraintLayout 布局最大的痛点废话不多说直接上配置：打开 Android Studio 设置 Editor -> General -> Code Completion 选项卡，然后如图设置。然后你会获得什么能力呢？来个 Gif 看看，千万要忍住惊讶！前方高能预警！高能预警！简单解释下我们调节的这个选项是干什么的，他是调整代码提示规则的这个选项有三个选项分别是 All、None、First letterAll代码提示规则是不区分大小写的，但是对单词顺序有要求，也就是拼写完全正确的才能提示出来None代码提示规则是不区分大小写的，但是对单词顺序也没有要求，也就是拼写能够模糊搜索到方法名或类名或变量名的就提示出来First letter代码提示规则是区分大小写，并且是对单词顺序有要求，也就是拼写完全正确（包括大小写）的才能提示出来总结看清楚没有各位观众老爷，各种喜欢啊，赞赏啊向我投过来，砸死我吧！

ConstraintLayout 实战经验
type: item
date: 2018-08-13T00:00:00+08:00
description: 这篇文章呢我们谈一谈，约束布局常用的一些需求和坑一、如果我想让一个控件在父布局里左右填充怎么办（上下填充，上下左右都填充同理）match_parent 方式<View android:id="@+id/a" android:layout_width="match_parent" android:layout_height="60dp" android:background="@android:color/holo_red_light" />相对布局的方式（android:layout_width="0dp" 是关键）<View android:id="@+id/a" android:layout_width="0dp" android:layout_height="60dp" android:background="@android:color/holo_red_light" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent" />ConstraintLayout 没有 match_parent 所以推荐使用第二种方式，虽然看效果是没啥事，但是官方的坑我表示不踩二、替代百分比布局有时候想把控件按照比例填充父布局，Android 屏幕适配这么复杂，好像不容易实现这时候约束布局有两个属性 layout_constraintWidth_percent layout_constraintHeight_percent这岂不是把一直不温不火的百分比布局给革命了<View android:id="@+id/a" android:layout_width="0dp" android:layout_height="50dp" android:background="@android:color/holo_red_light" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent" app:layout_constraintWidth_percent="0.3" />我只放这么一段代码大家应该就知道怎么用了，我也就不多了说了。默认是居中的如果想调整位置请结合 app:layout_constraintHorizontal_bias="0.3" 食用三、控件宽度一定，我想左右居中显示怎么办（上下居中同理）<View android:id="@+id/a" android:layout_width="120dp" android:layout_height="60dp" android:background="@android:color/holo_red_light" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent" />与左右填充相似，只不过宽度固定了而已，两条绳子拉着一个控件居中四、控件宽度一定，左右按百分比显示怎么办，我就是不想居中（上下同理）<View android:id="@+id/a" android:layout_width="120dp" android:layout_height="60dp" android:background="@android:color/holo_red_light" app:layout_constraintHorizontal_bias="0.3" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent" /> app:layout_constraintHorizontal_bias="0.3" 一个属性就搞定了上下使用 app:layout_constraintVertical_bias 来实现五、我想两个控件左右平分空间，对没错就是抢 LinearLayout 的饭碗（上下居中同理）<View android:id="@+id/a" android:layout_width="0dp" android:layout_height="60dp" android:background="@android:color/holo_red_light" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toLeftOf=…

ConstraintLayout 炫酷的动画
type: item
date: 2018-08-08T22:19:00+08:00
description: 谷歌之前推出了 ConstraintLayout 动画，做一些基本的动画让我们更省时省力了，今天我们就看一下这个小知识点。首先你需要引入 constraint-layout 这就不用我多说了然后还需要引入 transition 包，如果不引入，从而使用系统自带的 transition 的话，则你的约束布局动画只能兼容到 API 19implementation 'com.android.support.constraint:constraint-layout:1.1.2' implementation 'com.android.support:transition:27.1.1'我们先说一说最简单的实现方式，使用两个布局，第一个是我们正常的布局，另一个是记录控件变换后位置与约束信息的布局首先贴上正常的布局<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:id="@+id/root_layout" tools:context=".MainActivity"> <View android:id="@+id/a" android:layout_width="0dp" android:layout_height="60dp" android:background="@android:color/holo_red_light" app:layout_constraintHorizontal_weight="1" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toLeftOf="@+id/b" /> <View android:id="@+id/b" android:layout_width="0dp" android:layout_height="60dp" android:background="@android:color/holo_blue_light" app:layout_constraintHorizontal_weight="2" app:layout_constraintLeft_toRightOf="@+id/a" app:layout_constraintRight_toRightOf="parent" /> </android.support.constraint.ConstraintLayout>预览下原始布局然后贴上标定位置的布局<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity"> <View android:id="@+id/a" android:layout_width="0dp" android:layout_height="60dp" android:layout_margin="20dp" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent" app:layout_constraintTop_toTopOf="parent" /> <View android:id="@+id/b" android:layout_width="0dp" android:layout_height="60dp" android:layout_margin="20dp" app:layout_constraintLeft_toLeftOf="par…

最强大的布局 ConstraintLayout
type: item
date: 2018-08-08T21:49:00+08:00
description: 我之前写过一篇 ConstraintLayout 的文章现在已经到了 2018 年，最新正式版本也已经到了 1.1.2 ，又加了不少好用的特性，可以说这个约束布局已经成为 Android 中最强大的布局了，绝对不是吹嘘。本篇文章只会讲怎么使用代码画布局，可视化的方式精准度方面还是有点差强人意，如果你想了解可视化方式，请看我之前的文章。让我们看一看这个 Android 中最强大的布局吧！相对定位一、基本用法相对定位约束布局最基本也最常用的使用方式我们先简单看一下用法<TextView android:id="@+id/a" android:layout_width="60dp" android:layout_height="wrap_content" android:layout_marginLeft="20dp" android:layout_marginRight="20dp" android:gravity="center" android:layout_marginTop="30dp" app:layout_constraintTop_toTopOf="parent" app:layout_constraintLeft_toLeftOf="parent" android:text="A"/> <TextView android:id="@+id/b" app:layout_constraintTop_toTopOf="@+id/a" app:layout_constraintLeft_toRightOf="@+id/a" android:layout_width="60dp" android:layout_height="wrap_content" android:gravity="center" android:text="B" />我们先看 A 控件，A 的位置怎么来的呢？app:layout_constraintTop_toTopOf="parent" A 的顶边与 parent 的顶边对齐app:layout_constraintLeft_toLeftOf="parent" A 的左边与 parent 的左边对齐我们看到 A 与左边上边都有一个空隙， 这就是普通的 android:layout_marginXXXX 属性，我也就不细说了我们再看 B 控件，B 的位置怎么来的呢？app:layout_constraintTop_toTopOf="@+id/a" B 的顶部与 A 的顶部对齐app:layout_constraintLeft_toRightOf="@+id/a" B 的左边与 A 的右边对齐B 控件我没有设置 margin 所以他们是贴在一块的从上面的例子我们看到了两个问题看到两个控件 app:layout_constraintXXX_toXXXOf="xxx" 属性的值不一样，一个写的是控件 ID，一个是 parent ，这是什么意思呢？一般控件去约束需要一个参照物，这个参照物标识可以是控件的 ID ，也可以是父布局（父容器) —— parent就好比一根绳子一端拴在当前控件的某一位置，另一端拴在参照物的某一个位置上，这就建立起了约束。如果仔细看上述代码，大家肯定还有一个疑问，我明明在 A 控件上设置了 marginRight 为什么 A 和 B 还是贴着的，这就有一个说法，如果一个边没有约束那么他对应边的 margin 是不生效的OK 理解起来很简单不是吗，约束布局最基本的语法就是 app:layout_constraint位置_to位置Of="看齐目标" 那么像这种普通的相对定位的写法有多少种呢，我来给你们列举一下，再配张图标出它们的具体位置，看完下面基本的约束布局用法你就已经了解了。layout_constraintLeft_toLeftOf layout_constraintLeft_toRightOf layout_constraintRight_toLeftOf layout_constraintRight_toRightOf layout_constraintTop_toTopOf layout_constraintTop_toBottomOf layout_constraintBottom_toTopOf layout_constraintBottom_toBottomOf layout_constraintBaseline_toBaselineOf layout_constraintStart_toEndOf layout_constraintStart_toStartOf layout_constraintEnd_toStartOf layout_constraintEnd_to…

Android开发需要了解的网络协议
type: item
date: 2018-06-04T21:32:00+08:00
description: 我们先讲个小故事理解一下。盛唐年间，天下安定，由于疆域太大传递信件不易，就有民间的能人异士向皇帝谏言，每个州县都建立信息司来养信鸽。由信鸽来传递信件。皇帝觉得可行遍开始施行。一日皇帝命小吏从东都洛阳发一封信件到西京，这个小吏第一次去信息司发信件，到了信息司发现只有一个人处理信件。小吏便把信件交给了信息司的小哥，只见小哥娴熟的拿出只信鸽告诉它去西京，就放飞了，然后将信件誊抄了一份，将信件撕成了三份，并标上了序号。过了不一会小哥刚刚放走信鸽飞回来了，只见小哥又将信鸽放飞了。然后拿出三个信鸽分别将三份信件绑到信鸽的腿上，然后将信鸽放飞了。这时候小吏就问了小哥一句：”为什么刚刚只把信鸽放飞而不放信件啊！“。这时小哥不耐烦地说：”我要试试，我们州县附近有没有猎人，看看信鸽能不能飞出去。如果飞不出去就要找县衙派兵沿途检查一下路线了。“；小吏又问：”既然我们已经看到信鸽飞回来了，为什么还要再次放出去。“。小哥继续说：”西京那边还不知道他能不能发信鸽。我需要告诉他一声。“，谈话间只看到传递 1，3 号信件的鸽子飞回来了。小哥说：”又有一只鸽子飞丢了。“，小吏急忙问道：”怎么办！如果出了差错，我可是要被杀头的。“。小哥说：”莫着急我们再等一柱香的时间，如果还不回来我们在把 2 号信件重新发一次就好了。“。一炷香过后，小哥又拿出一只信鸽把 2 号信件绑到鸽子的腿上。不一会传递 2 号信件的信鸽飞回来了。只见小哥又娴熟的拿出一只信鸽放了出去，不一会飞回两只，然后小哥又放出去一只信鸽。小吏不解的问小哥：”你这个在干什么！“。小哥说：“我这是再告诉西京那边我的信息发完了。然后西京告诉我他知道了并让我把备份的信件销毁。我再告诉西京没问题”。终于皇帝的信件发完了。小吏回去后感觉比较有意思，东都西京中间隔着两个州，信鸽是怎么如何飞的呢？他又专程去问了信息司的小哥。小哥说：”我也不知道信鸽会飞到那个州，如果信鸽飞到其他州，其他州的人会看到信鸽的目的地是西京，他会改变信鸽的飞行方向，直到信鸽飞到西京才算结束。“。以上的小故事就是个简单 TCP 传输。小吏便算是应用层，皇帝让他去发消息。信息司的小哥身兼传输层和网络层。信鸽便是链路层。TCP/IP 分层网络1. 应用层应用层决定了向用户提供应用服务时通信的活动。TCP/IP 协议族内预存了各类通用的应用服务。例如：HTTP、SSH、FTP 等。2. 传输层应用层的下一层就是传输层，提供处于网络连接中的两台计算机之间的数据传输常见的传输层协议有 TCP、UDP 等。3. 网络层网络层又称网络互连层。网络层用来处理在网络上流动的数据包，数据包是网络传输的最小数据单位。该层规定了通过怎样的路径到达对方的计算机，并把数据包传送给对方。网络层的作用就是在众多选项内选择一条合适的传输路径。4. 链路层链路层又称数据链路层，网络接口层用来处理连接网络的硬件部分，控制操作系统、硬件的设备驱动。我们能够看到的交换机、网线、光纤等也属于物理层TCP 是什么TCP 的全称是传输控制协议（Transmission Control Protocol）位于传输层，它是一种有连接的协议，提供可靠的字节流服务[注1]。而可靠的传输服务是指，能够将数据准确可靠的传递给对方。数据为何能准确无误的送达目标处，就是因为 TCP 协议采用了三次握手策略，当然除了三次握手，TCP 协议还有其他手段来保证通信的可靠性TCP 三次握手发送端首先发送一个带 SYN 标志的数据包给对方接收端收到标有 SYN 的数据包后回传一个带有 SYN/ACK 标志的数据包表示确认信息发送端在发送一个带有 ACK 标志的数据包给接收端表示握手成功如果握手成功后连接断开，再次连接还需要重新握手TCP 四次挥手由于TCP连接时全双工的，因此，每个方向都必须要单独进行关闭，这一原则是当一方完成数据发送任务后，发送一个FIN来终止这一方向的连接，收到一个FIN只是意味着这一方向上没有数据流动了，即不会再收到数据了，但是在这个TCP连接上仍然能够发送数据，直到这一方向也发送了FIN。首先进行关闭的一方将执行主动关闭，而另一方则执行被动关闭。第一次挥手：Client发送一个FIN，用来关闭Client到Server的数据传送，Client进入FIN_WAIT_1状态。第二次挥手：Server收到FIN后，发送一个ACK给Client，确认序号为收到序号+1（与SYN相同，一个FIN占用一个序号），Server进入CLOSE_WAIT状态。第三次挥手：Server发送一个FIN，用来关闭Server到Client的数据传送，Server进入LAST_ACK状态。第四次挥手：Client收到FIN后，Client进入TIME_WAIT状态，接着发送一个ACK给Server，确认序号为收到序号+1…

Android 的 ClassLoader
type: item
date: 2018-04-28T14:45:00+08:00
description: 文章目录Android 中有哪几种 ClassLoader？他们的作用和区别是什么？简述 ClassLoader 的双亲委托模型简述双亲委托模型在热修复领域的应用首先了解下 ClassLoader 是什么众所周知我们编写的 Java 程序编写的是 .java 文件，但是在运行运行前会将代码编译成 .class 文件，以 Android Studio 项目为例在一般在项目目录下的 /build/intermediates/classes/debug 文件夹中有很多小文件夹，点进去看这些都是 .class 文件，程序在运行时就是加载这些 .class 文件，那么负责加载这些 .class 文件的就是我们的 ClassLoaer。一般在 Android 中程序打包会把多个 .class 文件打包成一个或多个 .dex 文件1. Android 中有哪几种 ClassLoader？它们的作用和区别是什么？我们先看一下Android源码有几个 ClassLoader 我们发现 ClassLoader 是个抽象类并且有两个子类 SecureClassLoader 、BaseDexClassLoaderSecureClassLoader 的子类是 URLClassLoader ，其只能用来加载 jar 文件，然而 jar 文件在 Android 的 Dalvik/ART 上没法使用的。BaseDexClassLoader 的子类是 PathClassLoader 、DexClassLoader 和 InMemoryDexClassLoader （ API 26 添加 ）。PathClassLoader 还有一个子类是 DelegateLastClassLoader （ API 27 添加 ）如果 jar 文件中包含 .dex 文件也是可以使用 BaseDexClassLoader 加载的那我们就分析一下 BaseDexClassLoader 的几个子类PathClassLoaderPathClassLoader 是一个简单的 ClassLoader 实现、Android 使用此类作为其系统类加载器和其应用程序类加载器。也就是说 PathClassLoader 在应用启动时创建，只能加载已经安装到 Android 系统中的apk文件（/data/app目录下，解压为 dex 后优化为 odex）。经过代码调用发现 PathClassLoader 的 parent 是 java.lang.BootClassLoader 这应该是最上层的 ClassLoader。DelegateLastClassLoaderDelegateLastClassLoader 是一个实现先查找再委托的类加载器实现protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException { Class<?> cl = findLoadedClass(name); if (cl != null) { return cl; } try { return Object.class.getClassLoader().loadClass(name); } catch (ClassNotFoundException ignored) { } ClassNotFoundException fromSuper = null; try { return findClass(name); } catch (ClassNotFoundException ex) { fromSuper = ex; } try { return getParent().loadClass(name); } catch (ClassNotFoundException cnfe) { throw fromSuper; } }首先在当前加载器查找是否加载过这个类。然后，尝试搜索此类的类加载器是否加载过这个类。使用当前加载器尝试去加载类最后委托给父加载器加载。DexClassLoaderDexClassLoader 就不一样了他可以在可读取目录中加载 .dex 文件以及包含 .dex 的 .jar 、.zip 和 .apk 文件，比 PathClassLoader 更灵活，是实现热修复的关键。这个加载器只有一个构造方法 public DexClassLoader(String dexPath, String optimizedDirectory, String librarySearchPath, ClassLoader parent) 其中 optimizedDirectory 是用来缓存优化过的类或代码的， AP…