Kotlin 的延迟初始化委托属性 by lazy

Kotlin 的延迟初始化委托属性 by lazy 详细解释:


📖 代码拆解

kotlin 复制代码
private val viewModel: NewsViewModel by lazy {

可以拆分为几个部分:

部分 含义
private 私有访问修饰符,外部无法访问
val 只读属性(类似 Java 的 final)
viewModel 属性名称
: NewsViewModel 属性类型
by lazy 使用延迟初始化委托

🔄 lazy 的工作原理

1. 延迟初始化

kotlin 复制代码
// 使用 lazy 的写法
private val viewModel: NewsViewModel by lazy {
    AppModule.provideNewsViewModel()
}

等价的 Java 写法:

java 复制代码
private NewsViewModel viewModel;

private NewsViewModel getViewModel() {
    if (viewModel == null) {
        viewModel = AppModule.provideNewsViewModel();
    }
    return viewModel;
}

2. 执行时机

时机 说明
声明时 ❌ 不执行
第一次访问时 ✅ 执行初始化
后续访问 ✅ 直接返回缓存值

例子:

kotlin 复制代码
private val viewModel: NewsViewModel by lazy {
    println("初始化 ViewModel")  // 这行只会在第一次访问时执行
    AppModule.provideNewsViewModel()
}

fun onCreate() {
    println("onCreate 开始")
    // viewModel 还没初始化
    println(viewModel.newsList)  // 此时才初始化,打印 "初始化 ViewModel"
    println(viewModel.newsList)  // 直接返回缓存,不打印
}

💡 为什么使用 lazy

1. 性能优化

kotlin 复制代码
// 不使用 lazy(每次创建 MainActivity 都会初始化)
private val viewModel = AppModule.provideNewsViewModel()  // 立即执行

// 使用 lazy(只在第一次访问时初始化)
private val viewModel: NewsViewModel by lazy {
    AppModule.provideNewsViewModel()  // 延迟执行
}

2. 避免循环依赖

kotlin 复制代码
class MainActivity {
    private val viewModel by lazy { NewsViewModel(repository) }
    private val repository by lazy { NewsRepository() }
    
    // 如果不用 lazy,repository 还没初始化就传给 viewModel 会报错
}

3. 简化代码

kotlin 复制代码
// 不使用 lazy
private lateinit var viewModel: NewsViewModel

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    viewModel = AppModule.provideNewsViewModel()
}

// 使用 lazy
private val viewModel: NewsViewModel by lazy {
    AppModule.provideNewsViewModel()
}

🎯 在项目中的实际应用

完整代码:

kotlin 复制代码
class MainActivity : ComponentActivity() {

    // 延迟初始化 ViewModel
    private val viewModel: NewsViewModel by lazy {
        AppModule.provideNewsViewModel()
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        setContent {
            AndroidFireTheme {
                // 第一次访问 viewModel 时才初始化
                val selectedNews by viewModel.selectedNews.collectAsState()
                
                if (selectedNews != null) {
                    DetailScreen(news = selectedNews!!, onBack = { ... })
                } else {
                    HomeScreen(viewModel = viewModel, onNewsClick = { ... })
                }
            }
        }
    }
}

🔄 lazy vs lateinit 对比

特性 lazy lateinit
类型 只读(val 可变(var
初始化时机 第一次访问时 手动赋值
线程安全 默认线程安全 不安全
可空性 不可空 可空
适用场景 只读属性、延迟初始化 可变属性、依赖注入

💻 实际例子

例子1:普通延迟初始化

kotlin 复制代码
private val expensiveObject: ExpensiveObject by lazy {
    println("开始初始化...")
    Thread.sleep(2000)  // 模拟耗时操作
    ExpensiveObject()
}

fun test() {
    println("1")
    println(expensiveObject)  // 第一次访问,开始初始化
    println("2")
    println(expensiveObject)  // 第二次访问,直接返回缓存
    println("3")
}

// 输出:
// 1
// 开始初始化...
// ExpensiveObject@123
// 2
// ExpensiveObject@123
// 3

例子2:线程安全的 lazy

kotlin 复制代码
private val threadSafeValue by lazy(LazyThreadSafetyMode.SYNCHRONIZED) {
    // 确保只有一个线程执行初始化
    "thread-safe"
}

🎓 总结

要点 说明
作用 延迟初始化,只在第一次访问时执行
优势 性能优化、避免循环依赖、代码简洁
线程安全 默认线程安全(SYNCHRONIZED 模式)
适用场景 只读属性、初始化耗时、依赖其他属性

简单理解by lazy 就是"懒加载",用的时候才初始化,不用就不初始化,节省资源!

相关推荐
Kapaseker4 小时前
我常用的 5 个 Kotlin 优化小技巧
android·kotlin
名剑走天下5 小时前
Kotlin_LiveData
开发语言·kotlin
JMchen1231 天前
Jetpack 内核实战(九):实战(上)——记事本首页列表 + 搜索功能开发
kotlin·android 实战·记事本 app 开发·recyclerview 优化·jetpack 综合实战
pengyu1 天前
【Kotlin 协程修仙录 · 炼虚境 · 初阶】 | 虚空造物:Channel 基础与协程间通信的管道艺术
android·前端·kotlin
小强闯江湖1 天前
ViewCompose:让原生 Android View 进入声明式时代
android·开源·kotlin
雨白1 天前
Kotlin 委托机制:搞懂“老板与秘书”模式
kotlin
pengyu2 天前
【Kotlin 协程修仙录 · 化神境 · 后阶】 | 异常天劫:Flow 异常处理的终极奥义与重试之道
android·kotlin
pengyu2 天前
【Kotlin 协程修仙录 · 化神境 · 中阶】 | 多播奥义:SharedFlow 高级配置与 Channel 的抉择之道
android·kotlin
撩得Android一次心动2 天前
Kotlin 语言【知识点整理2】
android·开发语言·kotlin
Android打工仔3 天前
Kotlin 协程源码解析(五):BaseContinuationImpl.resumeWith() —— Continuation 链是如何被展开的?
android·kotlin