26、Kotlin与Android开发:从项目搭建到实战技巧

说实话,Kotlin 刚出来那会儿,我还在用 Java 写 Android。当时觉得「又多一门语言要学,烦」。直到我在一个中型项目里被 NullPointerException 折磨到凌晨三点……嗯,从那以后,我彻底倒向了 Kotlin。

这一章,咱们就来聊聊 Kotlin 在 Android 开发中到底怎么用。我会从项目搭建开始,一步步带你感受 Kotlin 的优势,再深入到 Activity 和 Fragment 的写法,最后聊聊 Anko 这个库——虽然现在用得少了,但它的设计思路依然值得学习。

本章核心脉络: 搭建项目 → 理解优势 → 实战写法 → 工具库探索

Kotlin Android 开发知识体系 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)

这一行自动生成了:gettersetter(如果是 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 objectnewInstance 模式来解决:

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 的协程机制,那才是真正的大招。


公众号:蓝海资料掘金营,微信deep3321