Android 开发成长有益的技能推荐
Android 开发不仅涉及 UI 绘制,还需掌握版本管理、外语能力、后台技术、脚本编写及数据库等技能。Git 用于版本控制与分支策略;英语有助于阅读文档与开源交流;后台技术可辅助假数据生成与接口测试;脚本提升自动化效率;跨平台技术如 Flutter 增加职业选择。建议结合 CI/CD 与 SQL 知识完善全栈能力,促进职业发展。

Android 开发不仅涉及 UI 绘制,还需掌握版本管理、外语能力、后台技术、脚本编写及数据库等技能。Git 用于版本控制与分支策略;英语有助于阅读文档与开源交流;后台技术可辅助假数据生成与接口测试;脚本提升自动化效率;跨平台技术如 Flutter 增加职业选择。建议结合 CI/CD 与 SQL 知识完善全栈能力,促进职业发展。

做 App 开发,表面工作好像就是画 UI。但实际上涉及到的点不少,而且很多还蛮复杂的。以 Android 开发为例,是否专精 Android 就够了呢?我个人感觉不是的,多学点其它方面的东西对自己的职业生涯是有益的,而且也能反补回 Android 的开发上来。那计算机行业各种各样的知识,哪些才能对 App 开发者有益,或者说有更大益处的呢?本文就是想抛砖引玉,也希望能帮助到一些初级中级的开发者。
在版本管理上,我使用过最初的 CVS(好慢)、SVN(单分支)、Git。可能现在应该是 Git 为主流了吧,已经好多年没见过 SVN 了,更不用提最早的 CVS 了。而 Git 自己也并不是简单的 git commit、git push 这么简单啦。下面就挑几个有用的方面,希望对还不知道的同学有益处。
当你正在做一个 feature,结果来了个紧急 bug,只好丢弃手上的工作(feat 分支),转开另一个 fix 分支来解决 bug。这时 feat 分支上已经有的工作怎么办?
我以前不会 git stash 时,用的办法就是 clone 三个我们的代码库。这样一个库做一个分支。基本上就够用了。碰到上面的情况,我不用切分支,用 Android Studio 打开另一个仓库就行了。
当然,要是你的 Mac 硬盘不这么够,如只有 256GB,可能对于一些大仓库(如几个,甚至十几个 G),这种方法就不太适合了。
这时你可以用 git stash 来存储你的工作。等解决完了 bug,再切回 feat 分支,用 git stash pop 来取出刚刚存储的工作。
git stash //把本地的修改保存起来,再把分支变成最初的状态
git stash save -m "save message" //进阶版的保存,加上自己的注解来标识这次的保存是个什么东东
git stash list //查看有多少个保存的快照
/* 结果类似这样的:
stash {0} branch_name1 "save message1"
stash {1} branch_name2 "save message2"
stash {2} branch_name3 "save message3"
*/
git stash pop // 取出第一个快照,即 stash {0}, 并恢复到 IDE 里
git stash apply stash@{2} // 取出 index = 2 的快照, 即 stash {2}, 并恢复到 IDE 里
若是想多次提交,但只有一次提交记录,那就可以用 amend 的 commit。
若是 git amend 过一次,并 push 到远端了。这时再 push 就会出问题。这时就需要:git push -f,表示是 force push。
刚开始从事开发工作时,我更习惯于在 IDE 中操作 Git。但当有了冲突,并且自己解决了冲突后,我却总是苦于在 IDE 中找不到一个 "conflict resolved" 的按钮。
其实这时你只要 git add 这个文件,即把这个冲突文件重新加入到 git 里,就算向 git 表示,这个文件的冲突已经得到解决了。后续你就可以提交与 push 了。
Git hook 就相当于 git 提交器。一些常用的使用场景有:
这个技术上不是问题。不过我实践操作过,发现这样让 push 变得慢多了,开发人员 Push 个代码还要等好久,有点难受。
所以我目前就没有加任何 git hook 到我们工程里。要单元测试之类的就在远端 CI/CD 上做,不在本地做,就不影响开发的时间了。
我见过最多的两种策略就是:
1).
2).
这两种策略都行,我个人更倾向于第二种方式。因为我对于'长期独立于 main 分支之外的工作分支 (或 release 分支,或是 epic 分支,…)',都有种不放心。因为以后要是合起 main 分支,可能就要去解决很多很多问题。所以我更倾向方案 2,即只有短期游离在 main 分支之外的 release 分支 (是在快发版了时才创建的分支,发版了就合并到 main 上来了)。
p.s. 对于 Android 开发,可能没什么太大感觉。但对于 iOS 开发,每个开发的新加或删除文件都会触动 project.pbxproj 文件的修改,这样大家再合起来时就很容易有冲突。当年我在开发 RN 时,就吃过这方面不少的苦头。
总之,就是要尽量让所有非 main 分支的分支,生命短一些,免得最后合并时一堆冲突。
这个基本上所有开发都是初高中就学过英语了。但对于英语的掌握可能有多有少。我个人感觉还是有必要学习门外语的。
一个是外国好多书籍,等引入版权,再等翻译,排版,印刷,…可能要花一两年才能看到中文。若是你英语可以,你可以直接看国外的英文技术书籍,不能等翻译了,相当于你又可以看中文书,又可以看英语书,学习知识的渠道就变多了。
二是 github 上,和别人交流,如提交 pull request,可能就得用英语。
三是很多文档,可能就是英文的。比如最新的 iOS, android, kotlin, swift 等文档都还是英文的。你为了了解,也不得不学英文。
上面是书面英语。要是你想在口语或听力上有所进展,方便你以后出国工作或是和国外同事交流,你可以分两步来: 1). 工作英语:多从技术书籍,技术博客上学习如何描述一种技术上的行为 2). 生活英语:你可以多听听六人行的音频之类,很生活化,又不是很难。我以前学习英语时,把六人行的音频当成音乐一样,来回播了几十次,对于外国人的生活化用语,语气腔调,个别俚语慢慢熟练了。
当然,你要是主要做对日软件外包,像大连等地方就不少对日的软件开发,可能就要学点日语。
或者你对 Ruby 感兴趣,很多 Ruby 书籍以日语为多,你也可以学点日语。
总之,就是学门外语,多一些吸收知识的渠道。
现在少有 app 不联网了,这就造成了:我们 app 开发,其实学一点点后台知识,也有益于我们的日常 app 开发工作。
看你的喜好啦,
我个人做过 React Native,因此学过 JavaScript 与 TypeScript,所以我更喜欢用 Node.js 与 Express。而且 Node.js 的相关资料较多,有问题时很方便查阅。
若需求出来了,但后台的开发工作要几天后才能完成。在这时,你就可以用自己的后台技术,提前搞出一个自己小型服务器,让自己和 app 开发团队的其它同学来访问它,先得到假数据,从而能不 delay 移动端的开发工作。
一个小技巧就是,你不用自己去写 response 返回什么样的 json 数据,你完全可以放一个 json 文件放到后台工程里,这样返回时就直接访问这个静态文件就行了。以 Node.js 为例,那就是:
const express = require("express");
const app = express();
app.use(express.static("../public"));
// 这会把 public 目录中的所有文件当成静态文件,可以直接被 mobile 端访问到。
比如后台 tech lead 和你说,他们的新接口可能会返回个 304 给你,让你看着 etag 来决定访问的结果。这时你可能就不知道 HttpClient, HttpUrlConnection,或是 OkHttp 这些 mobile 端的网络工具会如何处理 etag,要你自己去存储上一次后台接口的数据吗?要自己存储每次的 etag 吗?offline 时也能得到数据吗?
为了验证你的这些疑问,你可以自己写一个后台,来看下 OkHttp 如何处理这些工作:
app.get("/data", (req, resp) => {
app.set("etag", true);
const requestVersion = req.headers["if-none-match"];
const eTag = "W/20220307";
resp.setHeader("ETag", eTag);
if (eTag === requestVersion) {
console.log(`/data 命中 etag`);
resp.statusCode = 304;
resp.end();
} else {
console.log(`/data 无匹配,返回新数据`);
resp.json({ id: 34, name: "banana", price: 0.5 });
}
});
若是你想测试一下 skeleton 的 shimmer 效果,或是 loading 的动画是否正常,但正常访问后台,得到数据太快了,看不到效果。这时怎么办?
或是你想测试 mobile 端的请求 timeout 是否有效,你就需要后台接口迟迟不给你响应。
正常的公司后台很难满足你的这种需求。这时你就可以用自己的后台,来模拟这种情况
app.get("/data", async function(req, resp) {
const result = generateRandomWord(count);
// 做到了延时的效果,这样来模拟网络较慢的情形,或是想看 loading 动画时
await waitMs(3000);
console.log(`response returns`)
resp.json(result);
});
const waitMs = (n) => new Promise((resolve) => setTimeout(resolve, n));
同理,除了自己的后台能很方便地给出延时,你自己的后台也能很方便地给出 error。这样你就可以测试你代码中的关于出错时的 edge case 了。
比如我最近在搞一些视频播放的研究。我使用我们公司的后台视频,也使用 google 上的测试视频。但只要用多了几次 (如一小时 10 次以上),再想访问,这些网站就会禁止我访问,说什么找不到这个 storage.googleapis.com 这个 hostname 了,其实是我访问过于频繁,视频体量又大,所以它们暂时把我给 ban 了。
这时要测试网上视频播放,我只要把这些视频下载下来 (当我解禁了时),然后放到我本地 server 上。以后我再在 mobile 端测试时,就不用 https://storage.googleapis.com/xx.mp4 了,我就直接使用:http://192.168.x.xx/yy.mp4 就行,总都不会有限流的,非常方便了我的网上视频播放的需求。
从上面几种场景来看,学习一门后台技术,真真很有必要。特别是你越进阶,跟后台的协作就越多,这时你的一些提前研究,自主的,不依赖于后台的自己的服务器就能帮到你很多次。
脚本就是一些简单的自动化工具,比如说每天几点上传 build 包到仓库里,每次提交要求检查 Lint,自动把 kotlin-android-extensions 的写法转成 ViewBinding 的写法 (kotlin 1.8 已经没有了 KAE 了),…
这种工具能大大解放人力,也就提高了开发的效率,是很有必要的存在。那使用什么来写脚本呢?
java 写起来还蛮累的,一个简单的 hello world 都要包到一个类里。所以不在考虑范围之内。其它的,如 Python, Ruby, Groovy 都可以用来写脚本。甚至我在 github 上还看过 Jake Wharton 以前就用 kotlin 写过脚本,比如说 diffuse。
这些语言的特点就是能直接用,不用包到一个类里去。所以使用起来很方便。
我个人极其喜欢 ruby,以及跟 ruby 很像的 Groovy。特别是 Groovy,天生兼容 java,同时处理起 xml 与 json 时又很方便。所以我的大多数脚本都是用的 Groovy。
总结:这一小节就是讲要学一门易上手的新的编程语言,主要就是用来写各种脚本。
若是你时间有限,暂时也不接触数据库,那这里可以放一放。
若你的 app 里大量使用了数据库,那 SQL 这块最好深入了解一下。不然你连出现了一些数据库错误,都不知道什么意思。
这里的知识包括但不限于:
好在 SQLite 比较小,你完全可以下载一下 SQlite 下来,然后在命令行里创建一个 DB,然后就用 SQL 语言来练手。
CI/CD 全称就是 continuous integration,以及 continuous deployment,也就是持续集成,持续部署。
说人话就是'这个服务器会自己打包,会自己发包到某一平台 (如 Firebase App distribution)'。
这样一个智能化的工具,其实就是一个后台服务器,它一般会监听你的提交,然后有提交了时,就会触发整个 app 的 build,最后把打出来的 apk, ipa, dmg, exe…文件发到一个平台上,供 QA 拿来测试。
上面说的只是基本功能。你完全可以定制自己的额外功能,如:
CI/CD 的最主要作用就是做到总在 build,即敏捷开发中提倡的,有问题就早早发现,不要等 release 时了才发现。
相关的 CI/CD 工具不少的。像我们公司在用的 CircleCI,以及 Github 上的 Github Action。它们的配置文件一般都是 yaml 文件。
这些服务一般是一开始不收费的,只有运行时间超过一定量了,才会开始向你收费。所以作为个人开发,你完全可以自己去挑一个 CI/CD 服务器,写一点 CI/CD 的配置文件出来,练练手,只要不太过量,就不会向你收费的。
这其实是从长期的职业规划上来讲的。因为我发现好多高层 boss,特别是非技术的 boss,一听到'跨平台'三个字就颅内高潮,以为'跨平台 = 低成本','跨平台 = 一次编写多处运行',以及'跨平台 = 更少开发人员/成本'。于是在很多公司都开始推荐跨平台了。
也就是说,我们 app 开发多学一门跨平台技术,也算是有一条后路。
这个问题我很早就考虑过,我个人的感觉是'native 开会仍是刚需,是不会消亡的'。
原因有多个: 1). 跨平台并不意味着你不需要 native 知识。像我做 React Native 时,我就经常要去 Android 与 iOS 端做一些原生的工作,做完后把结果发给 React Native 端。所以严格来说,做跨平台工作,其实是对 native 开发的要求更高了,要求你对 Android, iOS,甚至是 web 端都要熟练。 2). 移动端的版本更新很快,几乎 Android 与 iOS 是一年一个大版本,每个版本都有些新功能或新的限制。而跨平台明显跟不上这样的节奏的。以 Android 6 来说,Android 6 当年引入了运行时请求权限,这个东东,React Native 就不能支持。这时,要么你自己去 Android 平台写请求的代码,要么就让 targetSDK 不更新,这样拖个一年半载,让 RN 去解决这个问题 (当然,RN 可能不会解决,最终还是要靠你自己) 3). 目前主流的诸多跨平台技术,全是跨平台 UI框架。跟 UI 无关的工作,如 Location request, permision grant,…这些全得下沉到 native 平台去做。
综上所述,跨平台是不会取代 native 的,而且 native 仍是很重要的。
现在的跨平台开发越来越成熟了。我以前写 React Native 时写得欲仙欲死,恨不得马上离职,RN 的编写体验真的好差。更麻烦的是,一到了项目后期,一调试性能,各种 RN 的坑导致性能极差,我们做为开发要做各种补救。
但现在很多框架都有了越来越友好的跨平台体验了。比如说 Flutter, Compose, Kotlin Multiplatform,…
这些里面我个人更喜欢 Flutter,一个是出来得早,资料更多;二是比较有活力,官方的支持越来越多,现在连桌面端都想 cover;再就是渲染性能比 RN 也好一些。
这个其实是第 7 点'跨平台技术'的延伸。比如说我在 Flutter 或 React Native 里写一个文件的解密功能,这个不是 UI,所以不被 Flutter 与 RN 所支持。
好吧,其实也有 crypto-js 这样的库支持 ArrayBuffer 级别 (即 java 里的 byte 级别) 的解密,但我试了下,发现数据大时很慢,这时我就只好正常到 native 端去做解密工作。结果就是果然解密快多了。
回归正题,正因为是跨平台,所以我的原生插件就得既支持 Android,又得支持 iOS。于是我被逼无奈,去学了 Objective-C 的解密算法。于是相同的解密算法在 Android 端实现一次,在 iOS 端实现一次,两个 native 平台成功解密后再把结果给 RN 端。
所以说,多移动平台的开发都懂一点,会帮助到我们的跨平台开发。
我主业是 Android 开发,但自从我学会了 objc 与 swift 后,每当我碰到一些疑难问题,想看下 iOS 怎么弄的时,我只要打开 xcode 看下他们 iOS 的代码,就知道怎么弄了。所以会 iOS 的代码能帮到我们理解甚至是学习到 iOS 的一些做法。这对于 mobile 端的协作,或是 Mobile 端的统筹规划还是有用的。
这一点类似上面的第 8 点。一般同学可能用不上。但:

微信公众号「极客日志」,在微信中扫描左侧二维码关注。展示文案:极客日志 zeeklog
查找任何按下的键的javascript键代码、代码、位置和修饰符。 在线工具,Keycode 信息在线工具,online
JavaScript 字符串转义/反转义;Java 风格 \uXXXX(Native2Ascii)编码与解码。 在线工具,Escape 与 Native 编解码在线工具,online
使用 Prettier 在浏览器内格式化 JavaScript 或 HTML 片段。 在线工具,JavaScript / HTML 格式化在线工具,online
Terser 压缩、变量名混淆,或 javascript-obfuscator 高强度混淆(体积会增大)。 在线工具,JavaScript 压缩与混淆在线工具,online
将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online
将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online