这个附录是给谁的
如果你看到下面这些话里有任何一个不懂,就该读这个附录:
- “变量”、“函数”、"循环"是什么?
- 命令行怎么用?
cd是什么意思?为什么路径有D:\和/两种写法?- 为什么书里说
0x47?24 字节、f16(2 字节)是什么意思?- “一个汉字占 3 个字节”——为什么?乱码方块是怎么产生的?
- JSON 是什么?为什么要"序列化"?
- CPU、内存、进程、线程、虚拟机——这些词听过但说不清。
- Git 是什么?为什么要
clone?如果你已经懂这些,可以跳过本附录,直接读 ch01。
本附录不涉及 Android,只讲"读这本书需要的最小常识"。怎么用本附录:不用从头背。遇到不懂的词,回这里查对应小节。
每节末尾都有"在本项目哪里用到",告诉你去哪一章看它真正的样子。
A.1 编程的最基本概念
这一节假设你从没写过代码。如果你写过任何一门语言,可以快速浏览。
A.1.1 程序是什么
程序 = 给计算机的、一步一步的操作说明。
💡类比
程序像菜谱:先切菜、再热锅、再下油、再翻炒……
计算机(电脑/手机)只会严格按你写的顺序执行,不会"猜到你想干什么"。
所以顺序、每一步是否说清楚,比"聪明"重要得多。
一个程序通常包含几种最基本的"动作":
| 动作 | 作用 | 类比 |
|---|---|---|
| 变量 | 记住一个值 | 给抽屉贴标签,把东西放进去 |
| 条件判断 | 根据情况走不同路 | “如果下雨,带伞” |
| 循环 | 重复做同一件事 | “把碗一个个洗,直到洗完” |
| 函数 | 把一组操作打包,起个名字 | 菜谱里的"炒个底料"(可复用) |
A.1.2 变量与类型
变量就是一个"有名字的盒子",里面放一个值。
score = 100 ← 把 100 放进名叫 score 的盒子 name = "离线AI" ← 把文字放进名叫 name 的盒子类型= 这个盒子里装的是"哪一类东西"。常见类型:
| 类型 | 装什么 | 例子 |
|---|---|---|
| 整数 | 整数 | 42、-7、8999 |
| 浮点数 | 带小数的数 | 0.3、3.14159 |
| 字符串 | 一段文字 | "你好"、"Q4_K_M" |
| 布尔值 | 真 / 假 | true、false |
| 列表 | 一串东西 | [1, 2, 3]、["a", "b"] |
⚠️为什么要有类型?
因为计算机对"数字 42"和"文字 "42""的处理完全不同:
数字可以做加法,文字不行。类型告诉计算机该怎么处理。
在本项目哪里用到:ch03 讲 Kotlin 的val/var与类型;ch14 讲 GGUF 元数据的 13 种类型。
A.1.3 函数
函数 = 一段"可以反复使用"的操作,有一个名字。
函数:算两个数的和 输入:a, b 输出:a + b 用的时候: 算两个数的和(3, 4) → 得到 7| 术语 | 含义 |
|---|---|
| 参数 | 函数需要的输入(上例的a、b) |
| 返回值 | 函数给出的结果(上例的7) |
| 调用 | "使用"一个函数这个动作 |
💡类比:函数像洗衣机上的按钮。
你按"标准洗"(调用),它内部有一大堆步骤(洗、漂、脱水),
但你不需要知道细节,只要按按钮。
这就是函数的两个好处:复用(按多次)+封装(不用管内部)。
在本项目哪里用到:ch03 讲 Kotlin 函数;ch13 讲"Kotlin 怎么调用 C++ 函数"。
A.1.4 条件判断与循环
条件判断(走不同的路):
如果 温度 > 30: 开空调 否则: 开窗循环(重复做):
对列表里的每一个 消息: 显示它在本项目哪里用到:ch16 的生成循环(while (!_cancelGeneration))、
ch18 的分批解码(for循环)。
A.1.5 数据结构(容器)
现实程序里,"一个值"很少够用,往往要装一堆值:
| 结构 | 特点 | 类比 |
|---|---|---|
| 列表 / 数组 | 有顺序,可按下标取 | 排队的队伍 |
| 字典 / Map | 键 → 值,按键查 | 字典(按词查释义) |
| 对象 / 类 | 一组相关字段打包 | 一张表格(姓名、年龄、地址) |
在本项目哪里用到:
- 列表:
List<Message>(消息列表,ch03); - Map:GGUF 元数据是
Map<String, MetadataValue>(ch14); - 对象:
Message/ChatSession/ModelInfo都是(ch03)。
A.1.6 类和对象(面向对象)
类 = 一张"设计图纸";对象 = 按图纸造出来的具体东西。
类(图纸):Message 字段:id、content、isUser 对象(具体实例): 消息1 = Message(id="a1", content="你好", isUser=true) 消息2 = Message(id="b2", content="你好呀", isUser=false)| 术语 | 含义 |
|---|---|
| 字段 / 属性 | 类里存的"数据" |
| 方法 | 类里能做的"操作"(相当于属于这个类的函数) |
| 实例化 | 按类造出一个对象(也叫"创建对象") |
在本项目哪里用到:ch03 讲data class;MainScreenState是一个"类"(ch09)。
A.1.7 库、框架、依赖
| 词 | 含义 | 类比 |
|---|---|---|
| 库(Library) | 别人写好的一堆函数,你拿来用 | 五金店里买现成的螺丝 |
| 框架(Framework) | 别人定好的"程序骨架",你在指定位置填代码 | 买好的毛坯房(水电都通了,你只管装修) |
| 依赖(Dependency) | 你的项目需要的别人的库 | 菜谱里说"需要现成的酱油" |
在本项目哪里用到:
- 库:Gson(转 JSON,ch11)、llama.cpp(推理引擎,ch14);
- 框架:Jetpack Compose(界面框架,ch06)、Gradle(构建框架,ch20);
- 依赖:全部列在
gradle/libs.versions.toml(ch02)。
A.1.8 SDK、API、IDE
| 词 | 全称 / 含义 | 一句话 |
|---|---|---|
| SDK | Software Development Kit | 一整套开发工具(编译器、工具、文档) |
| IDE | Integrated Development Environment | 写代码的软件(如 Android Studio) |
| API | Application Programming Interface | 别人提供的"函数清单",你照它调用 |
| 编译 | Compile | 把源码"翻译"成机器能执行的形式 |
| 运行 | Run | 让程序真正执行 |
在本项目哪里用到:
- SDK:Android SDK(ch02);
- API:
llama_decode、llama_model_load_from_file都是 llama.cpp 提供的 API(ch15); - 编译:Kotlin 编译、C++ 编译(ch20)。
A.2 命令行与文件路径
为什么必须懂命令行:本书大量操作用命令行完成(构建、校验、看日志)。
比"会用鼠标点"更重要的是理解路径——因为大部分报错都和路径有关。
A.2.1 什么是命令行
命令行(CLI)= 用打字给计算机下命令的界面(对比"用鼠标点"的图形界面)。
为什么开发常用命令行:
- 可复制、可分享(把命令贴给同事就行,不用截图说明点了哪里);
- 可脚本化(写进脚本,一次跑一批);
- 信息更全(报错原文完整显示,不被界面省略)。
打开方式(Windows):按Win + R,输入powershell或cmd,回车。
A.2.2 最常用的几条命令
| 目的 | Windows (PowerShell) | 说明 |
|---|---|---|
| 看当前在哪 | pwd | 显示当前目录 |
| 进入某个目录 | cd C:\dev\llamacpptest | change directory |
| 返回上一级 | cd .. | ..表示"上一级" |
| 列出目录内容 | ls(或dir) | list |
| 新建目录 | mkdir 新名字 | |
| 复制文件 | copy 源 目标/Copy-Item | |
| 看文件内容 | type 文件/Get-Content | 小文件可以,大文件会刷屏 |
| 清屏 | cls |
⚠️本书所有
gradlew命令,都必须在llama.android目录下执行——
因为gradlew是那个目录里的文件。"在哪个目录执行"是新手最常见的错误来源之一。
A.2.3 路径:绝对路径 vs 相对路径
| 类型 | 长什么样 | 含义 |
|---|---|---|
| 绝对路径 | C:\dev\llamacpptest\llama.android | 从盘符(或根)开始,完整 |
| 相对路径 | llama.android、..\llama.cpp | 相对当前位置 |
两个特殊符号:
| 符号 | 含义 |
|---|---|
. | 当前目录 |
.. | 上一级目录 |
所以..\..\llama.cpp的意思是"上两级,再进 llama.cpp"。
在本项目哪里用到:ch20 讲的LLAMA_SRC就是../../../../../llama.cpp(上溯 5 级)——数错层数是最常见的构建报错之一。
A.2.4 斜杠还是反斜杠?
| 场合 | 写法 | 例子 |
|---|---|---|
| Windows 命令行的路径 | 反斜杠\ | C:\dev\... |
| 绝大多数编程语言/配置文件 | 正斜杠/ | C:/dev/...、llama.android/app/... |
| Windows 其实也认正斜杠 | ✅ | C:/dev也能用 |
💡建议:写代码/配置时一律用正斜杠
/**。
它在 Windows、macOS、Linux 上都通用,能避免一类转义问题。📌但有个例外:Java 的
.properties文件里,反斜杠是转义字符,
所以写C:\dev\Android\Sdk会被解析错,必须写成C:\\dev\\Android\\Sdk或改用C:/dev/Android/Sdk。
这正是 ch02 讲的local.properties那个坑。
A.2.5 环境变量
环境变量 = 系统里的一些"全局设置",程序可以读它们。
例子:
JAVA_HOME:Java 装在哪;PATH:系统去哪找可执行程序(所以你才能直接敲java)。
怎么读(PowerShell):
echo$env:JAVA_HOME在本项目哪里用到:ch02 讲"为什么本项目不依赖 PATH,而是在gradle.properties里写死 JDK 路径"。
A.3 数字在计算机里怎么存
为什么必须懂:本书里反复出现
0x47、24 字节、8192、f16(2 字节)、小端序——不理解这些,ch14/ch16/ch18 会读不下去。
A.3.1 位(bit)与字节(byte)
| 单位 | 含义 |
|---|---|
| 位(bit) | 最小的单位,只能是0或1 |
| 字节(byte) | 8 个位= 一个字节 |
换算:
1 字节(byte) = 8 位(bit) 1 KB = 1024 字节 1 MB = 1024 KB 1 GB = 1024 MB💡为什么是 1024 而不是 1000?
因为计算机用二进制,1024 = 2¹⁰。
所以"2.0 GB 的模型"其实是 2 × 1024 × 1024 × 1024 ≈ 21.5 亿字节。
在本项目哪里用到:
- ch01 讲"7B Q4 量化后约 3.5–4 GB";
- ch10 讲"导入中途失败残留 GB 级半成品";
- ch15 算"KV cache 约 4 GB"(
2 × 32 × 8192 × 4096 × 2 字节)。
A.3.2 二进制与十六进制
二进制:只有0和1。计算机内部全是二进制。
十六进制:用0–9和A–F共 16 个符号表示,每 1 位十六进制 = 正好 4 位二进制,
所以它比二进制短,写起来方便。
| 十进制 | 二进制 | 十六进制 |
|---|---|---|
| 0 | 0000 | 0 |
| 10 | 1010 | A |
| 15 | 1111 | F |
| 16 | 10000 | 10 |
| 71 | 0100 0111 | 47 |
| 255 | 1111 1111 | FF |
写法约定:0x开头表示十六进制。所以0x47= 十进制的 71。
在本项目哪里用到:
ch14 讲 GGUF 的 magic 是0x47 0x47 0x55 0x46——
翻成 ASCII 就是G G U F(见 A.4)。
A.3.3 “小端序”:多字节数字的存放顺序
一个数字如果超过 1 字节(比如 4 字节的整数),这几个字节谁在前?
| 方式 | 规则 |
|---|---|
| 小端序(little-endian) | 低位字节放前面(低地址) |
| 大端序(big-endian) | 高位字节放前面 |
例子:数字1用 4 字节存:
小端序:01 00 00 00 ← 数值 1 在最前面 大端序:00 00 00 01 ← 要看到最后才看到 1这就是为什么 GGUF 的 version = 3 存成03 00 00 00。
在本项目哪里用到:ch14 的readLEUInt32(LE就是 little-endian);
读错字节序 = 全盘皆错。
A.3.4 浮点数与"精度"
浮点数= 带小数的数。计算机用"科学计数法"的形式存它。
关键问题:精度不同、占的字节数不同。
| 类型 | 占字节 | 大概能表示的位数 | 常见称呼 |
|---|---|---|---|
| FP32(单精度) | 4 | 约 7 位有效数字 | float |
| FP16(半精度) | 2 | 约 3–4 位 | f16、half |
| INT8 | 1 | 整数 −128~127 | int8 |
| INT4 | 0.5(“半个字节”) | 16 个取值 | Q4 |
📌这就是 ch01 讲的"量化":
把 FP16(2 字节)压成 INT4(0.5 字节),体积缩 4 倍。
所以"7B 模型 FP16 约 14 GB → Q4 约 3.5–4 GB"。也解释了 ch15 的 KV cache 计算:KV cache 默认用 f16,所以每个数值算2 字节。
A.4 文本编码:为什么"一个汉字 3 字节"、为什么会乱码
为什么必须懂:ch16 讲了一个核心机制——“汉字被 token 切成两半导致乱码”,
以及 33 行的 UTF-8 校验函数。不懂编码就读不懂那一章。
A.4.1 计算机只认数字
字符(A、中、😀)在计算机里都是数字。
"编码"就是"字符 ↔ 数字"的对照规则。
A.4.2 ASCII:最早的编码
ASCII 只覆盖英文字母、数字、常用符号,每个字符用1 字节。
| 字符 | ASCII 码(十六进制) |
|---|---|
G | 0x47 |
U | 0x55 |
F | 0x46 |
A | 0x41 |
0 | 0x30 |
所以 GGUF 文件的头 4 字节47 47 55 46就是 “GGUF”(✅ ch14 讲的就是这个)。
⚠️ASCII 的问题:只有 128 个字符,装不下中文、日文、emoji。
A.4.3 UTF-8:现代通用编码
UTF-8 的特点:变长编码——不同字符占不同字节数。
| 字符类型 | 占字节 | 例子 |
|---|---|---|
| 英文/数字(ASCII 范围) | 1 | a=61 |
| 拉丁扩展、希腊文等 | 2 | é=C3 A9 |
| 中日韩汉字 | 3 | 中=E4 B8 AD |
| emoji 等 | 4 | 😀=F0 9F 98 80 |
这就是"一个汉字 3 个字节"的由来。
A.4.4 UTF-8 的字节结构(关键)
UTF-8 用字节的高几位来表示"这个字符总共几字节":
| 首字节模式 | 表示 | 后续字节数 |
|---|---|---|
0xxxxxxx | 单字节(ASCII) | 0 |
110xxxxx | 双字节 | 1 |
1110xxxx | 三字节(汉字) | 2 |
11110xxx | 四字节(emoji) | 3 |
| 其它 | ❌ 非法 | — |
后续字节必须以10xxxxxx开头。
A.4.5 乱码是怎么产生的
如果一段字节不满足上面的规则,就不是合法的 UTF-8,
显示时通常变成�(乱码方块)。
在本项目里,这个"非法"是怎么产生的?
因为模型是按 token 输出的,而token 边界可能落在字符的中间:
"中" = E4 B8 AD 模型可能这样输出: token A → E4 B8 ← 只有 2 个字节,不是完整的 UTF-8 token B → AD ← 补上第 3 个字节如果你在 token A 之后就把E4 B8转成字符串 → 非法 → 乱码方块。
✅ 本工程的解法(ch16.5):先攒着,等凑成合法 UTF-8 再发。
那个 33 行的is_valid_utf8函数做的就是"按上面的规则逐字节检查"。
💡一个记住它的办法:
“半个字不是字”—— 宁可晚一点显示,也不能显示半个字。
A.5 JSON:程序之间传数据的"通用格式"
为什么必须懂:ch11 讲持久化时,会话列表就是存成 JSON 的。
A.5.1 它长什么样
JSON 是一种文本格式,用来表示结构化数据:
{"id":"a1b2c3","title":"新对话","messages":[{"id":"m1","content":"你好","isUser":true},{"id":"m2","content":"你好呀","isUser":false}],"createdAt":1757000000000}结构要素:
| 符号 | 含义 |
|---|---|
{ } | 一个"对象"(一组键值对) |
[ ] | 一个"列表" |
"键": 值 | 键值对(键必须是带引号的字符串) |
| 值是字符串 | 要带双引号 |
| 值是数字 | 不用引号 |
| 值是真假 | true/false |
A.5.2 序列化与反序列化
| 术语 | 方向 | 含义 |
|---|---|---|
| 序列化 | 对象 → 文本 | 把内存里的对象"拍扁"成 JSON 字符串 |
| 反序列化 | 文本 → 对象 | 把 JSON 字符串"复原"成对象 |
为什么需要它?
因为"存到磁盘"和"网络传输"都只能处理文本/字节,
而程序内部用的是对象。所以两边要转换。
在本项目哪里用到(ch11):
gson.toJson(list)→ 序列化(存盘);gson.fromJson(json, ...)→ 反序列化(读盘)。
📌ch11 讲的"坏 JSON 兜底":因为 JSON 是纯文本,
可能被改坏、被截断。反序列化失败时必须兜住,否则整个列表读不出来。
A.6 CPU、内存、进程、线程
为什么必须懂:ch01 讲"为什么手机能跑大模型"、ch08 讲"为什么不能用 Thread"、
ch10 讲"ANR"——都建立在这些概念上。
A.6.1 CPU:负责"算"
CPU(中央处理器)= 计算机里负责执行指令、做运算的部件。
| 相关词 | 含义 |
|---|---|
| 核心(core) | CPU 里能独立干活的小单元(8 核 = 能同时做 8 件事) |
| 主频 | 每秒能做多少次操作(越高越快) |
| 指令集 | CPU 认识哪些"指令"(不同 CPU 不一样) |
在本项目里:
- ch01 讲"本工程跑在 CPU 上"(不是 GPU);
- ch15 讲"线程数 = 核数 − 2,最多 4";
- ch20 讲的ABI(arm64-v8a / x86_64)就是"CPU 的架构/指令集":
手机几乎都是 arm64,电脑/模拟器常见 x86_64。
A.6.2 内存(RAM):负责"记"
内存 = 程序运行时的"工作台",程序的数据要放在这里才能被 CPU 使用。
| 特点 | 说明 |
|---|---|
| 快 | 比磁盘快非常多 |
| 断电即失 | 关机就没了(所以需要"存盘") |
| 有限 | 手机常见 8–16 GB |
在本项目里:
- ch01 讲"一个 4 GB 的模型在 8 GB 内存手机上基本跑不起来";
- ch15 讲"内存占用 = 模型权重 + KV cache";
- ch04/ch09 讲"切后台要释放模型腾内存"。
💡"存内存"和"存磁盘"的区别(本书反复出现):
内存(RAM) 磁盘(存储) 速度 极快 慢很多 关机后 没了 还在 本项目例子 聊天记录(ViewModel) 聊天记录(DataStore) 这就是 ch04 讲的"旋转屏幕记录不丢(在内存里)“vs"退出重开还在(在磁盘里)”。
💡什么是"缓存(cache)"?
缓存 = “算过一次的东西先放着,下次直接用,不重算”。
它通常放在快的存储(内存)里,因为重算慢、重读快。
本书最大的缓存就是KV cache(ch15/ch18):
历史对话的计算结果存起来,每新说一句话只算新的,不用把整段历史重算一遍。
A.6.3 进程与线程
| 概念 | 含义 | 类比 |
|---|---|---|
| 进程(Process) | 一个正在运行的程序 | 一家公司的办事处 |
| 线程(Thread) | 进程内的一条执行流 | 办事处里的一个员工 |
关键点:
| 事实 | 说明 |
|---|---|
| 一个进程可以有多个线程 | 可以"同时"做几件事 |
| 同进程的线程共享内存 | 所以能互相看到对方的数据(也所以要小心"抢"数据) |
| 不同进程的内存是隔离的 | 所以要通信必须走特殊机制(见 A.6.4) |
在本项目里:
- ch01 讲"整个 App 从头到尾只有一个
InferenceEngine实例"(进程内单例); - ch08 讲"主线程不能被阻塞"、“用后台线程跑推理”;
- ch12 讲"TTS 回调跑在 Binder 线程"——和主线程不同的线程,所以要加锁。
A.6.4 跨进程通信(IPC)与 Binder
因为不同进程的内存隔离,一个 App 想用系统或别的 App的能力,
就得通过一套通信机制——Android 上叫Binder。
Binder 的一个关键限制:一次能传的数据有大小上限(约 1MB)。
在本项目里:ch11/ch12 讲的"导出对话不能直接塞EXTRA_TEXT"——
就是因为长对话会超过 Binder 上限(TransactionTooLargeException),
所以要走"写文件 + 给一个content://URI"。
💡这也解释了为什么叫"跨进程":
“把文件分享给别的 App” = 两个不同的进程在通信。
A.7 "编译"是怎么把代码变成 App 的
为什么必须懂:ch01/ch20 讲构建流程,ch13 讲"为什么要有 JNI"。
A.7.1 三种执行方式
| 方式 | 过程 | 例子 |
|---|---|---|
| 编译型 | 源码 →机器码→ 直接给 CPU 执行 | C / C++ |
| 解释型 | 源码 → 逐行解释执行 | Python |
| 混合型(虚拟机) | 源码 → 中间码 → 虚拟机执行 | Java / Kotlin(跑在 ART 上) |
在本项目里:
- Kotlin跑在 Android 的ART 虚拟机上(ch01);
- C++编成机器码直接跑(ch13);
- 两者"语言、内存、调用规则都不一样",所以要JNI 桥(ch13)。
A.7.2 本项目的两条编译线
Kotlin 代码 → Kotlin 编译器 → .class → D8/R8 → classes.dex ┐ ├→ APK C++ 代码 → CMake + clang++ → .so(动态库) ┘ 资源(图标) → aapt2 → 编译后的资源 ┘这就是 ch20 讲的三条构建线。
A.7.3 什么是 APK
APK = Android 的安装包,本质是个zip 压缩包,里面装:
| 内容 | 是什么 |
|---|---|
classes*.dex | 编译后的 Kotlin/Java 代码 |
lib/<架构>/*.so | 编译后的 C++ 库 |
res/ | 资源(图标、文字等) |
resources.arsc | 资源索引表 |
AndroidManifest.xml | 那个"身份证"(ch04) |
📌所以
unzip -l xxx.apk能看到它的内部——
ch20/ch21 讲"判断 ABI 只看 APK",用的就是这条。
A.7.4 什么是 Gradle
Gradle = 构建工具:管"按什么顺序、用什么工具、把代码变成 APK"。
它做的事:
- 下载依赖;
- 调用编译器;
- 打包资源;
- 生成 APK;
- 签名。
在本项目里:gradlew就是"用工程自带版本的 Gradle"(ch02)。
A.8 Git 最小必需
为什么必须懂:本项目用 Git 管代码;书里也建议"每次只改一个变量"(ch22),
而 Git 正是那个"能精确回退"的工具。
A.8.1 Git 是什么
Git = 版本控制工具:记录"每一次改动",让你能:
| 能力 | 有什么用 |
|---|---|
| 看历史 | 三天前改了什么 |
| 对比差异 | 这次改动了哪些行 |
| 回退 | 改坏了,退回上一个能用的状态 |
| 分支 | 同时试验多个方案 |
💡类比:Git 像游戏的"存档点"。
每到一个里程碑就存一次档,玩崩了能读回去。
"不能回退"是新手最大的恐惧来源——有了 Git,这个恐惧就没了。
A.8.2 四条最常用的命令
| 命令 | 作用 |
|---|---|
git status | 看当前有哪些改动(最常用,能救命) |
git diff | 看具体改了什么内容 |
git add .+git commit -m "说明" | 把当前改动"存一个档" |
git log --oneline | 看历史存档列表 |
注意:commit只存在本地,不会自动上传。
A.8.3 关于clone
git clone <仓库地址>= 把一个远程仓库完整复制到本地(含所有历史)。
为什么很多教程让你先clone?
因为这样你拿到的不只是代码,还有完整历史——
能看到"这个文件是怎么一步步变成现在这样的"。这是学习真实项目的最好材料。
📌本项目的一个相关约定(ch21 强调过):
密钥文件(*.jks)和keystore.properties绝对不能提交到 Git。
因为它们一旦进了仓库,就等于"把公章复印件发给了所有能看到仓库的人"。
A.9 读这本书的建议姿势
A.9.1 遇到不懂的词怎么办
① 先查本附录(A.1–A.8) ② 再查《附录 B 术语表》(中英对照 + 一句话 + 出处章节) ③ 还没懂 → 去看那一章(术语表会写明"在哪一章详细讲") ④ 还是不懂 → 看《附录 C 常见问题》A.9.2 三条"不要"
| 不要 | 因为 |
|---|---|
| 不要试图一次记住所有词 | 术语是在使用中记住的,不是背出来的 |
| 不要跳过"动手验证" | 那才是"学会"和"看懂"的分界线(ch23 讲的) |
| 不要怕报错 | 报错是信息,不是失败。本书每章都有"如果失败了怎么办" |
A.9.3 一条"要"
要尽早让项目在你机器上跑起来。
哪怕那时还看不懂代码。
因为"跑起来"会给你正反馈,而且后面每次调试都有个可用的基线。
(这一条在 ch01 也强调过,值得再提一次。)
A.10 小结:这个附录讲了多少个概念
| 小节 | 概念 | 关键结论 |
|---|---|---|
| A.1 | 变量/函数/条件/循环/数据结构/类/库框架/SDK·API·IDE | 程序是"按顺序的说明书" |
| A.2 | 命令行/路径/斜杠/环境变量 | "在哪个目录执行"很重要 |
| A.3 | bit/byte/二进制/十六进制/小端序/浮点精度 | 1 字节 = 8 位;0x47=G |
| A.4 | ASCII/UTF-8/乱码 | 一个汉字 3 字节,“半个字不是字” |
| A.5 | JSON/序列化 | 存盘和传输只能处理文本 |
| A.6 | CPU/内存/进程/线程/Binder | 内存快但易失;Binder 有 1MB 上限 |
| A.7 | 编译/APK/Gradle | APK 是个 zip |
| A.8 | Git | 存档点,让你敢改代码 |
| A.9 | 学习姿势 | 别背术语、别跳验证、别怕报错 |
读懂了这个附录,你就可以开始读 ch01 了。
最后提醒:这个附录不是"读完就过"的。
读正文时遇到不懂的词,回来查——
用的次数多了,自然就记住了。