26、Kotlin与Android开发:从项目搭建到实战技巧
说实话,Kotlin 刚出来那会儿,我还在用 Java 写 Android。当时觉得「又多一门语言要学,烦」。直到我在一个中型项目里被 NullPointerException 折磨到凌晨三点……嗯,从那以后,我彻底倒向了 Kotlin。
这一章,咱们就来聊聊 Kotlin 在 Android 开发中到底怎么用。我会从项目搭建开始,一步步带你感受 Kotlin 的优势,再深入到 Activity 和 Fragment 的写法,最后聊聊 Anko 这个库——虽然现在用得少了,但它的设计思路依然值得学习。
本章核心脉络: 搭建项目 → 理解优势 → 实战写法 → 工具库探索
一、Android 项目搭建:Kotlin 版
现在用 Android Studio 创建项目,默认就能选 Kotlin。但在早期,你得手动配置。我记得第一次配的时候还踩了个坑——忘了加 kotlin-stdlib 依赖。
1.1 基础配置
在项目的 build.gradle(Module 级别)里,你需要做两件事:
// 1. 应用 Kotlin 插件
plugins {
id 'com.android.application'
id 'org.jetbrains.kotlin.android' // 这一行是关键
}
// 2. 确保 Kotlin 标准库被引入
dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib:1.9.0"
// 其他依赖...
}
小提示: 如果你用 Android Studio 2022 以上版本,创建项目时勾选「Include Kotlin support」,这些配置会自动生成。但我建议你还是看一眼,心里有数。
1.2 项目结构
Kotlin 源文件放在 src/main/java/ 目录下,和 Java 一样。但文件后缀是 .kt。我个人习惯按功能分包,比如:
ui/— 界面相关(Activity、Fragment、Adapter)data/— 数据层(Model、Repository、网络请求)utils/— 工具类(扩展函数、常量)
你想想看,这种结构在 Java 项目里也能用,但 Kotlin 的扩展函数让工具类变得特别优雅。后面我会讲到。
二、Kotlin 在 Android 中的优势
说白了,Kotlin 就是 Java 的「增强版」。但具体强在哪?我挑几个最实在的说说。
2.1 空安全 —— 告别 NullPointerException
在 Java 里,你写 String name = null; 然后调用 name.length(),直接崩。Kotlin 从类型系统层面解决了这个问题:
// 可空类型用 ? 声明
var name: String? = null
// 安全调用
val length = name?.length // 如果 name 为 null,length 也为 null
// Elvis 操作符
val len = name?.length ?: 0 // 如果 name 为 null,len = 0
我在项目中遇到过好几次线上崩溃,查下来都是 Java 空指针。换成 Kotlin 后,这类问题几乎绝迹。嗯,这里要注意:Kotlin 的空安全是编译期的,不是运行时。所以写代码时就能发现问题。
2.2 扩展函数 —— 给系统类加方法
这个特性我太喜欢了。比如你想给 View 加一个显示 Toast 的方法:
// 扩展函数
fun View.showToast(message: String) {
Toast.makeText(context, message, Toast.LENGTH_SHORT).show()
}
// 使用
button.showToast("点击了按钮")
在 Java 里你得写一个工具类 ToastUtil.showToast(button, "xxx")。Kotlin 的写法更自然,就像 View 本来就有的方法一样。
2.3 数据类 —— 少写一堆模板代码
Java 的 Bean 类要写 getter/setter、toString、equals、hashCode……烦不烦?Kotlin 一行搞定:
data class User(val id: Int, val name: String, val email: String)
这一行自动生成了:getter、setter(如果是 var)、toString()、equals()、hashCode()、copy()。我算过,至少省了 50 行代码。
2.4 协程 —— 异步任务不再头疼
Android 里网络请求、数据库操作都得异步。Java 用回调或 RxJava,代码容易嵌套。Kotlin 协程让异步代码看起来像同步:
// 在 ViewModel 中
fun loadUserData() {
viewModelScope.launch {
val user = withContext(Dispatchers.IO) {
apiService.getUser() // 网络请求在 IO 线程
}
// 回到主线程更新 UI
userName.text = user.name
}
}
我曾经在一个项目里用协程重构了 RxJava 的代码,行数减少了 40%,可读性提升了一大截。
三、Activity 与 Fragment 的 Kotlin 写法
这部分是实战重点。我直接上代码对比,你感受一下差异。
3.1 Activity 的 Kotlin 写法
Java 版:
public class MainActivity extends AppCompatActivity {
private Button btn;
private TextView tv;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btn = findViewById(R.id.btn);
tv = findViewById(R.id.tv);
btn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
tv.setText("点击了");
}
});
}
}
Kotlin 版:
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
// 使用 Kotlin Android Extensions 或 ViewBinding
btn.setOnClickListener {
tv.text = "点击了"
}
}
}
看到区别了吗?Kotlin 版少了 findViewById,少了匿名内部类,代码更简洁。我个人推荐用 ViewBinding,类型安全且性能好:
class MainActivity : AppCompatActivity() {
private lateinit var binding: ActivityMainBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
binding.btn.setOnClickListener {
binding.tv.text = "点击了"
}
}
}
3.2 Fragment 的 Kotlin 写法
Fragment 在 Kotlin 里同样简洁。这里有个常见的坑——Fragment 的构造函数不能带参数。我曾经用 companion object 加 newInstance 模式来解决:
class DetailFragment : Fragment() {
private var userId: Int = 0
companion object {
fun newInstance(userId: Int): DetailFragment {
val fragment = DetailFragment()
val args = Bundle()
args.putInt("user_id", userId)
fragment.arguments = args
return fragment
}
}
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
userId = arguments?.getInt("user_id") ?: 0
return inflater.inflate(R.layout.fragment_detail, container, false)
}
}
为什么用 companion object?因为 Fragment 框架会通过反射重建实例,带参数的构造函数会导致崩溃。这个坑我踩过一次,后来就老老实实用 newInstance 了。
四、Anko 库简介
Anko 是 JetBrains 推出的一个 Kotlin 库,主要用来简化 Android 开发。虽然现在官方已经不维护了,但它的设计思路很值得学习。
4.1 Anko 的核心功能
| 功能模块 | 说明 | 我的评价 |
|---|---|---|
| Anko Layouts | 用 Kotlin 代码写布局,替代 XML | 适合动态布局,但 XML 更直观 |
| Anko Commons | 简化 Intent、Toast、Dialog 等操作 | 非常实用,代码量减少明显 |
| Anko SQLite | 简化数据库操作 | Room 出来后基本不用了 |
| Anko Coroutines | 协程的扩展函数 | 现在官方协程库已经够用 |
4.2 Anko Commons 实战
我最常用的是 Anko Commons 里的简化操作。比如显示 Toast:
// 传统写法
Toast.makeText(this, "你好", Toast.LENGTH_SHORT).show()
// Anko 写法
toast("你好")
再比如启动 Activity:
// 传统写法
val intent = Intent(this, DetailActivity::class.java)
intent.putExtra("id", 123)
startActivity(intent)
// Anko 写法
startActivity("id" to 123)
你看,代码是不是清爽多了?虽然现在 Anko 不再更新,但这些简化思路已经被官方采纳了。比如 ActivityResultContracts 就借鉴了 Anko 的简洁风格。
注意: 不要在正式项目里引入 Anko 了。它已经停止维护,而且与最新的 Android 开发工具链(如 Compose)不兼容。但你可以学习它的 API 设计思想——好的设计永远不会过时。
五、小结
这一章我们聊了 Kotlin 在 Android 开发中的实际应用。从项目搭建到 Activity/Fragment 的写法,再到 Anko 库的启发。说白了,Kotlin 让 Android 开发变得更安全、更简洁、更高效。
我个人觉得,Kotlin 最大的价值不是语法糖,而是它改变了我们写代码的思维方式。空安全让你更自信,扩展函数让你更灵活,协程让你更轻松。如果你还在用 Java 写 Android,我建议你试试 Kotlin——哪怕只是一个小模块,你也能感受到差异。
嗯,下一章我们会深入 Kotlin 的协程机制,那才是真正的大招。