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 就是"懒加载",用的时候才初始化,不用就不初始化,节省资源!

相关推荐
传奇开心果编程12 小时前
【Compose Multiplatform 跨端开发学与练】第7课 平台适配与互操作
android·windows·学习·ui·ios·kotlin·composer
mmsx12 小时前
Android 地图数据链路:从 GDAL、KML 到多引擎适配
android·kotlin
事圆则缓15 小时前
Kotlin 泛型方差实战:out、in、星投影与类型擦除
android·开发语言·kotlin
传奇开心果编程17 小时前
【Compose Multiplatform 跨端开发学与练】第5课 网络与数据层
android·网络·学习·ui·ios·kotlin·composer
Android打工仔19 小时前
CoroutineScheduler 设计解析(上)—— 为什么 Dispatchers.IO 会创建更多线程?
android·kotlin·源码阅读
熊猫钓鱼>_>20 小时前
Kotlin Multiplatform for OpenHarmony 实战:为 kotlin-inject 实现依赖注入适配
开发语言·华为·kotlin·ai编程·inject·鸿蒙·openharmony
翼辉cto21 小时前
Kotlin Multiplatform 三方库 SQLDelight 的 OpenHarmony 鸿蒙化适配实战
开发语言·kotlin·harmonyos
熊猫钓鱼>_>1 天前
Kotlin Multiplatform for OpenHarmony 实战:为 KMPNotifier 实现 OpenHarmony 本地通知引擎
kotlin·ai编程·harmonyos·鸿蒙·openharmony·适配·kmp
传奇开心果编程2 天前
【Compose Multiplatform 跨端开发学与练】第3课 布局与组件
android·windows·学习·ui·ios·kotlin·composer
事圆则缓2 天前
Kotlin 入门与面试:从空安全、扩展函数到协程
安全·面试·kotlin