Skip to content

Kotlin 高级开发面试知识点汇总 🚀

Android 高级开发必备 Kotlin 核心知识点,包含详细示例代码和面试考点


目录

  1. 空安全 (Null Safety)
  2. 扩展函数与扩展属性
  3. 高阶函数与 Lambda
  4. 协程 (Coroutines)
  5. Flow 数据流
  6. 委托 (Delegation)
  7. 密封类 (Sealed Class)
  8. 内联函数 (Inline)
  9. 泛型与型变
  10. 作用域函数

1. 空安全

1.1 基础语法

kotlin
// 可空类型 vs 非空类型
var name: String = "Kotlin"        // 非空
var nullableName: String? = null   // 可空

// 安全调用操作符 ?.
val length = nullableName?.length

// Elvis 操作符 ?:
val nameOrEmpty = nullableName ?: "Default"

// 非空断言 !!
val length = nullableName!!.length  // 可能抛 NPE

// 安全转换 as?
val str: String? = obj as? String

1.2 面试考点

Q: 如何安全处理可空类型?

kotlin
// ✅ 推荐方案

// 1. 安全调用 + Elvis
fun getUserEmail(user: User?): String {
    return user?.email ?: "unknown@example.com"
}

// 2. let 作用域
fun processUser(user: User?) {
    user?.let {
        println("User name: ${it.name}")
        println("Email: ${it.email}")
    }
}

// 3. 平台类型处理(Java 互操作)
fun handleJavaString(javaStr: String?) {
    val safeStr = javaStr?.trim()?.ifEmpty { "default" } ?: "default"
}

// 4. 可空类型智能转换
fun checkUser(user: User?) {
    if (user != null) {
        // 智能转换为非空
        println(user.name)
    }
}

1.3 高级技巧

kotlin
// 可空类型的扩展函数
fun String?.isNullOrEmpty(): Boolean = this == null || this.isEmpty()

// 链式安全调用
fun getUserName(user: User?): String? {
    return user?.profile?.name?.trim()
}

// 可空类型的 Elvis 返回
fun validateUser(user: User?): Boolean {
    val name = user?.name ?: return false
    val email = user.email ?: return false
    return name.isNotEmpty() && email.contains("@")
}

2. 扩展函数与扩展属性

2.1 基础语法

kotlin
// 扩展函数
fun String.addPrefix(prefix: String): String {
    return "$prefix$this"
}

// 使用
val result = "Kotlin".addPrefix("Hello ")  // "Hello Kotlin"

// 扩展属性
val String.lastChar: Char
    get() = this[this.length - 1]

// 使用
val last = "Kotlin".lastChar  // 'n'

2.2 面试考点

Q: 扩展函数与成员函数的区别?

kotlin
// 扩展函数(静态解析)
class A
fun A.foo() = "extension"

class B {
    fun foo() = "member"
}

val a = A()
val b = B()

println(a.foo())  // "extension"
println(b.foo())  // "member"

// 扩展函数不能访问私有成员
class MyClass {
    private val secret = "hidden"
}

// ❌ 错误:无法访问 private 成员
// fun MyClass.getSecret() = secret

2.3 实战示例

kotlin
// 1. Context 扩展(Android 常用)
fun Context.showToast(message: String, duration: Int = Toast.LENGTH_SHORT) {
    Toast.makeText(this, message, duration).show()
}

fun Context.dpToPx(dp: Float): Int {
    return (dp * resources.displayMetrics.density).toInt()
}

fun Context.openUrl(url: String) {
    val intent = Intent(Intent.ACTION_VIEW, Uri.parse(url))
    startActivity(intent)
}

// 2. View 扩展
fun View.visible() {
    visibility = View.VISIBLE
}

fun View.gone() {
    visibility = View.GONE
}

fun View.invisible() {
    visibility = View.INVISIBLE
}

// 3. 集合扩展
fun <T> List<T>.safeGet(index: Int): T? {
    return if (index in indices) this[index] else null
}

fun <T> List<T>.firstOrNull(predicate: (T) -> Boolean): T? {
    return this.filter(predicate).firstOrNull()
}

// 4. String 扩展
fun String.isValidEmail(): Boolean {
    return this.contains("@") && this.contains(".")
}

fun String.toTitleCase(): String {
    return this.split(" ").joinToString(" ") { word ->
        word.replaceFirstChar { it.uppercase() }
    }
}

// 5. 可空类型扩展
fun String?.isNullOrBlank(): Boolean = this == null || this.isBlank()

fun <T> T?.letOrNull(block: (T) -> Unit) {
    this?.let(block)
}

3. 高阶函数与 Lambda

3.1 基础语法

kotlin
// 函数类型
val sum: (Int, Int) -> Int = { a, b -> a + b }

// 作为参数
fun operate(a: Int, b: Int, operation: (Int, Int) -> Int): Int {
    return operation(a, b)
}

// 作为返回值
fun getMultiplier(factor: Int): (Int) -> Int {
    return { x -> x * factor }
}

// 使用
val double = getMultiplier(2)
println(double(5))  // 10

3.2 面试考点

Q: Lambda 表达式的 it 关键字?

kotlin
// it 是默认参数名
val numbers = listOf(1, 2, 3, 4, 5)

// 使用 it
val doubled = numbers.map { it * 2 }

// 自定义参数名
val doubled = numbers.map { number -> number * 2 }

// 多个参数必须命名
val pairs = listOf(1 to "a", 2 to "b")
pairs.forEach { (num, str) ->
    println("$num: $str")
}

3.3 实战示例

kotlin
// 1. 自定义高阶函数
fun <T> List<T>.filterMap(
    predicate: (T) -> Boolean,
    transform: (T) -> String
): List<String> {
    return this.filter(predicate).map(transform)
}

// 使用
val result = listOf(1, 2, 3, 4, 5)
    .filterMap(
        { it % 2 == 0 },
        { "Number: $it" }
    )
// ["Number: 2", "Number: 4"]

// 2. 尾随 Lambda
fun performOperation(
    initialValue: Int,
    operation: (Int) -> Int
): Int {
    return operation(initialValue)
}

// 调用
val result = performOperation(10) {
    it * 2 + 5
}

// 3. 接收者函数类型
class Builder {
    var name: String = ""
    var age: Int = 0
}

fun build(block: Builder.() -> Unit): Builder {
    return Builder().apply(block)
}

// 使用
val person = build {
    name = "张三"
    age = 25
}

// 4. 挂起函数作为参数
suspend fun fetchData(
    url: String,
    onSuccess: (String) -> Unit,
    onError: (Throwable) -> Unit
) {
    try {
        val result = withContext(Dispatchers.IO) {
            // 网络请求
            "data"
        }
        onSuccess(result)
    } catch (e: Exception) {
        onError(e)
    }
}

4. 协程 (Coroutines)

4.1 基础语法

kotlin
// CoroutineScope
lifecycleScope.launch {
    // 协程代码
}

// launch vs async
val job = launch {
    // 不返回值
}

val deferred = async {
    // 返回值
    "result"
}
val result = deferred.await()

// Dispatchers
withContext(Dispatchers.IO) {
    // IO 操作
}

withContext(Dispatchers.Main) {
    // UI 操作
}

withContext(Dispatchers.Default) {
    // CPU 密集型计算
}

4.2 面试考点

Q: launch 和 async 的区别?

kotlin
// launch: 不返回值,适合火任务
launch {
    repository.saveData(data)
    showToast("保存成功")
}

// async: 返回值,需要 await()
val deferred1 = async { fetchData1() }
val deferred2 = async { fetchData2() }

// 并行执行
val result1 = deferred1.await()
val result2 = deferred2.await()

// 或者使用 awaitAll
val results = awaitAll(deferred1, deferred2)

Q: 协程作用域的区别?

kotlin
// lifecycleScope: 与生命周期绑定
lifecycleScope.launch {
    // Activity/Fragment 销毁时自动取消
}

// viewModelScope: 与 ViewModel 绑定
class MyViewModel : ViewModel() {
    init {
        viewModelScope.launch {
            // ViewModel clear 时自动取消
        }
    }
}

// CoroutineScope: 自定义作用域
class MyRepository {
    private val scope = CoroutineScope(Dispatchers.IO + SupervisorJob())
    
    fun loadData() {
        scope.launch {
            // 需要手动取消
        }
    }
    
    fun clear() {
        scope.cancel()
    }
}

// GlobalScope: 全局作用域(不推荐)
GlobalScope.launch {
    // 应用生命周期,容易内存泄漏
}

4.3 实战示例

kotlin
// 1. 顺序执行
suspend fun loadUserData() = viewModelScope.launch {
    val user = userRepository.getUser()      // 先执行
    val posts = postRepository.getPosts()    // 后执行
    updateUI(user, posts)
}

// 2. 并行执行
suspend fun loadUserDataParallel() = viewModelScope.launch {
    val userDeferred = async { userRepository.getUser() }
    val postsDeferred = async { postRepository.getPosts() }
    
    val user = userDeferred.await()
    val posts = postsDeferred.await()
    
    updateUI(user, posts)
}

// 3. 异常处理
suspend fun loadDataWithTryCatch() = viewModelScope.launch {
    try {
        val data = withContext(Dispatchers.IO) {
            repository.getData()
        }
        updateUI(data)
    } catch (e: Exception) {
        showError(e.message)
    }
}

// 4. SupervisorJob(子协程失败不影响其他)
val scope = CoroutineScope(SupervisorJob() + Dispatchers.Default)

scope.launch {
    val job1 = launch {
        // 失败不影响 job2
        throw Exception("Error 1")
    }
    
    val job2 = launch {
        // 继续执行
        doSomething()
    }
}

// 5. 超时处理
suspend fun loadDataWithTimeout() = withTimeoutOrNull(5000) {
    repository.getData()
} ?: run {
    // 超时处理
    showTimeoutError()
}

// 6. 重试机制
suspend fun loadDataWithRetry(
    maxRetries: Int = 3,
    delayMs: Long = 1000
): Data {
    var lastException: Exception? = null
    
    repeat(maxRetries) { attempt ->
        try {
            return repository.getData()
        } catch (e: Exception) {
            lastException = e
            if (attempt < maxRetries - 1) {
                delay(delayMs)
            }
        }
    }
    
    throw lastException ?: Exception("Unknown error")
}

// 7. 协程取消
val job = lifecycleScope.launch {
    while (isActive) {
        // 可取消的工作
        doWork()
        delay(1000)
    }
}

// 取消协程
job.cancel()

// 8. Flow 与协程结合
fun loadDataFlow(): Flow<Data> = flow {
    val data = repository.getData()
    emit(data)
}.flowOn(Dispatchers.IO)

// 收集
lifecycleScope.launch {
    loadDataFlow().collect { data ->
        updateUI(data)
    }
}

5. Flow 数据流

5.1 基础语法

kotlin
// 创建 Flow
val numbers: Flow<Int> = flow {
    for (i in 1..5) {
        emit(i)
        delay(100)
    }
}

// 收集 Flow
lifecycleScope.launch {
    numbers.collect { value ->
        println(value)
    }
}

// 操作符
numbers
    .map { it * 2 }
    .filter { it > 4 }
    .collect { println(it) }

5.2 面试考点

Q: Flow vs LiveData 的区别?

kotlin
// Flow 优势
// 1. 冷流(按需执行)
// 2. 丰富的操作符
// 3. 支持背压处理
// 4. 多平台支持

// LiveData 优势
// 1. 生命周期感知
// 2. 自动管理观察者
// 3. 配置更新保留数据

// 转换
fun asLiveData(): LiveData<T> = flow.asLiveData()
fun asFlow(): Flow<T> = liveData.asFlow()

5.3 实战示例

kotlin
// 1. StateFlow(状态流)
class ViewModel : ViewModel() {
    private val _uiState = MutableStateFlow<UiState>(UiState.Loading)
    val uiState: StateFlow<UiState> = _uiState.asStateFlow()
    
    init {
        viewModelScope.launch {
            _uiState.value = UiState.Loading
            _uiState.value = UiState.Success(data)
        }
    }
}

// 2. SharedFlow(共享流)
class EventBus {
    private val _events = MutableSharedFlow<Event>()
    val events: SharedFlow<Event> = _events.asSharedFlow()
    
    suspend fun postEvent(event: Event) {
        _events.emit(event)
    }
}

// 3. Flow 操作符组合
fun searchQueryFlow(query: String): Flow<List<Result>> = flow {
    val results = repository.search(query)
    emit(results)
}
    .flowOn(Dispatchers.IO)
    .debounce(300)           // 防抖
    .distinctUntilChanged()  // 去重
    .retry(3)                // 重试
    .catch { e ->
        emit(emptyList())
    }

// 4. 多个 Flow 组合
fun combineFlows(): Flow<Pair<User, Posts>> = combine(
    userFlow,
    postsFlow
) { user, posts ->
    user to posts
}

// 5. flatMapLatest(只取最新)
fun searchWithLatest(queryFlow: Flow<String>): Flow<List<Result>> {
    return queryFlow.flatMapLatest { query ->
        repository.searchFlow(query)
    }
}

// 6. 背压处理
val sharedFlow = MutableSharedFlow<Event>(
    replay = 0,           // 不重放
    extraBufferCapacity = 10,  // 缓冲容量
    onBufferOverflow = BufferOverflow.DROP_LATEST  // 溢出策略
)

6. 委托 (Delegation)

6.1 基础语法

kotlin
// 类委托
interface Base {
    fun print()
}

class BaseImpl : Base {
    override fun print() {
        println("BaseImpl")
    }
}

class Derived(b: Base) : Base by b

// 属性委托
class LazyExample {
    val value: String by lazy {
        println("computed!")
        "Hello"
    }
}

// 使用
val example = LazyExample()
println(example.value)  // 第一次:打印 "computed!" 然后 "Hello"
println(example.value)  // 第二次:只打印 "Hello"

6.2 面试考点

Q: by lazy 的实现原理?

kotlin
// lazy 三种模式
val lazy1 by lazy(LazyThreadSafetyMode.SYNCHRONIZED) { compute() }  // 默认,线程安全
val lazy2 by lazy(LazyThreadSafetyMode.PUBLICATION) { compute() }   // 多线程初始化,可能多次计算
val lazy3 by lazy(LazyThreadSafetyMode.NONE) { compute() }          // 单线程,最快

6.3 实战示例

kotlin
// 1. 自定义属性委托
class NotNullVar<T> {
    private var value: T? = null
    
    operator fun getValue(thisRef: Any?, property: KProperty<*>): T {
        return value ?: throw IllegalStateException("Property ${property.name} not initialized")
    }
    
    operator fun setValue(thisRef: Any?, property: KProperty<*>, value: T) {
        this.value = value
    }
}

class Example {
    var name: String by NotNullVar()
}

// 2. Observable 属性
import kotlin.properties.Delegates

class User {
    var name: String by Delegates.observable("<no name>") {
        prop, old, new ->
        println("$prop changed from $old to $new")
    }
}

// 3. 可空 Observable
var nullableName: String? by Delegates.vetoable(null) {
    prop, old, new ->
    new != null  // 返回 false 拒绝更新
}

// 4. Map 委托
class User(map: Map<String, Any?>) {
    val name: String by map
    val age: Int by map
}

val user = User(mapOf(
    "name" to "张三",
    "age" to 25
))
println(user.name)  // "张三"

// 5. 局部变量委托
fun example() {
    var name: String by Delegates.observable("") { _, old, new ->
        println("Changed from $old to $new")
    }
    name = "Kotlin"
}

// 6. 提供委托
class ResourceProvider {
    operator fun provideDelegate(
        thisRef: MyActivity,
        prop: KProperty<*>
    ): ReadOnlyProperty<MyActivity, String> {
        // 创建委托前执行
        return Property { _, _ -> "Value" }
    }
}

7. 密封类 (Sealed Class)

7.1 基础语法

kotlin
sealed class Result {
    data class Success(val data: String) : Result()
    data class Error(val message: String) : Result()
    object Loading : Result()
}

// 使用
fun handleResult(result: Result) {
    when (result) {
        is Result.Success -> println("Success: ${result.data}")
        is Result.Error -> println("Error: ${result.message}")
        Result.Loading -> println("Loading...")
    }
}

7.2 面试考点

Q: 密封类 vs 枚举类的区别?

kotlin
// 枚举类:只能有固定实例
enum class Status {
    SUCCESS, ERROR, LOADING
}

// 密封类:可以有多个子类,每个子类可以有不同状态
sealed class Status {
    object Success : Status()
    data class Error(val message: String) : Status()
    object Loading : Status()
}

7.3 实战示例

kotlin
// 1. API 响应状态
sealed class ApiResult<out T> {
    data class Success<T>(val data: T) : ApiResult<T>()
    data class Error(val code: Int, val message: String) : ApiResult<Nothing>()
    object Loading : ApiResult<Nothing>()
}

// 使用
suspend fun fetchData(): ApiResult<User> {
    return try {
        val user = api.getUser()
        ApiResult.Success(user)
    } catch (e: Exception) {
        ApiResult.Error(500, e.message ?: "Unknown error")
    }
}

// 2. UI 状态
sealed class UiState {
    object Initial : UiState()
    object Loading : UiState()
    data class Success(val data: List<Item>) : UiState()
    data class Error(val message: String) : UiState()
}

// ViewModel
class MyViewModel : ViewModel() {
    private val _uiState = MutableStateFlow<UiState>(UiState.Initial)
    val uiState: StateFlow<UiState> = _uiState.asStateFlow()
    
    fun loadData() {
        viewModelScope.launch {
            _uiState.value = UiState.Loading
            _uiState.value = try {
                val data = repository.getData()
                UiState.Success(data)
            } catch (e: Exception) {
                UiState.Error(e.message ?: "Error")
            }
        }
    }
}

// 3. 导航事件
sealed class NavigationEvent {
    data class NavigateToDetail(val id: String) : NavigationEvent()
    object NavigateBack : NavigationEvent()
    data class ShowDialog(val message: String) : NavigationEvent()
}

// 4. 当表达式必须 exhaustive
fun processState(state: UiState): String {
    return when (state) {
        is UiState.Initial -> "Initial"
        is UiState.Loading -> "Loading"
        is UiState.Success -> "Success with ${state.data.size} items"
        is UiState.Error -> "Error: ${state.message}"
    }
}

8. 内联函数 (Inline)

8.1 基础语法

kotlin
// 内联函数
inline fun <T> T.let(block: (T) -> R): R {
    return block(this)
}

// 使用
val result = "Kotlin".let {
    it.uppercase()
}

8.2 面试考点

Q: inline 的作用和原理?

kotlin
// 内联前
fun <T> T.let(block: (T) -> R): R {
    return block(this)  // 创建 Lambda 对象
}

// 内联后(编译后)
val result = "Kotlin".uppercase()  // 直接展开代码

8.3 实战示例

kotlin
// 1. 资源管理
inline fun <T : Closeable, R> T.use(block: (T) -> R): R {
    var exception: Throwable? = null
    try {
        return block(this)
    } catch (e: Throwable) {
        exception = e
        throw e
    } finally {
        try {
            close()
        } catch (e: Throwable) {
            if (exception == null) throw e
            exception.addSuppressed(e)
        }
    }
}

// 使用
FileInputStream("file.txt").use { fis ->
    // 自动关闭
}

// 2. 同步锁
inline fun <T> Any.synchronized(block: () -> T): T {
    return kotlin.synchronized(this, block)
}

// 3. 运行作用域
inline fun <T> T.run(block: T.() -> R): R {
    return block()
}

// 4. noinline(禁止内联)
inline fun test(
    inlineParam: () -> Unit,
    noinline noInlineParam: () -> Unit
) {
    inlineParam()  // 内联
    noInlineParam()  // 不内联,可以传递给其他函数
}

// 5. crossinline(禁止非局部返回)
inline fun test(crossinline block: () -> Unit) {
    val runnable = Runnable {
        block()  // 不能 return
    }
}

// 6. 内联类(值类)
@JvmInline
value class UserId(val value: String)

@JvmInline
value class Email(val value: String)

// 编译后直接是 String,没有对象开销
fun sendEmail(userId: UserId, email: Email) {
    // ...
}

9. 泛型与型变

9.1 基础语法

kotlin
// 泛型函数
fun <T> List<T>.safeGet(index: Int): T? {
    return if (index in indices) this[index] else null
}

// 泛型类
class Box<T>(val content: T)

// 泛型约束
fun <T : Comparable<T>> max(a: T, b: T): T {
    return if (a > b) a else b
}

// 多个约束
fun <T> where(
    T : Comparable<T>,
    T : Cloneable
) {
    // ...
}

9.2 面试考点

Q: in 和 out 关键字(型变)?

kotlin
// 协变(out):只能读
interface Producer<out T> {
    fun produce(): T
}

// 逆变(in):只能写
interface Consumer<in T> {
    fun consume(item: T)
}

// PECS 原则
// Producer Extends, Consumer Super
fun copy(
    from: Array<out Any>,  // 生产者
    to: Array<in Any>      // 消费者
) {
    for (i in from.indices) {
        to[i] = from[i]
    }
}

9.3 实战示例

kotlin
// 1. 星投影
fun printList(list: List<*>) {
    for (item in list) {
        println(item)
    }
}

// 2. 泛型约束
fun <T : Number> sum(list: List<T>): Double {
    return list.sumOf { it.toDouble() }
}

// 3. 泛型 reified(需要 inline)
inline fun <reified T> List<*>.filterIsInstance(): List<T> {
    return this.filterIsInstance<T>()
}

// 使用
val list = listOf(1, "hello", 2, "world")
val strings = list.filterIsInstance<String>()

// 4. 泛型工厂
interface Factory<T> {
    fun create(): T
}

class UserFactory : Factory<User> {
    override fun create() = User()
}

// 5. 泛型仓库
class Repository<T> {
    private val items = mutableListOf<T>()
    
    fun add(item: T) {
        items.add(item)
    }
    
    fun getAll(): List<T> = items
}

// 6. 泛型扩展
fun <T> T.toResult(): Result<T> {
    return Result.Success(this)
}

10. 作用域函数

10.1 对比表

函数对象引用返回值典型用途
letit结果空安全、变量作用域
runthis结果对象配置、计算
withthis结果对象操作(非扩展)
applythis对象本身对象初始化
alsoit对象本身副作用、日志

10.2 实战示例

kotlin
// 1. let - 空安全
val length = nullableString?.let {
    it.trim().length
} ?: 0

// 2. run - 对象配置
val textView = TextView(context).run {
    text = "Hello"
    textSize = 16f
    setPadding(16, 16, 16, 16)
    this  // 显式返回
}

// 3. with - 非扩展
with(textView) {
    text = "Hello"
    textSize = 16f
}

// 4. apply - 对象初始化
val intent = Intent().apply {
    action = Intent.ACTION_VIEW
    data = Uri.parse("https://example.com")
    putExtra("key", "value")
}

// 5. also - 副作用
val numbers = mutableListOf<Int>().also {
    println("Creating list with ${it.size} elements")
}
    .apply {
        add(1)
        add(2)
    }
    .also {
        println("List created: $it")
    }

// 6. 链式调用
val user = User().apply {
    name = "张三"
    age = 25
}.also {
    Log.d("User", "Created: $it")
}.let {
    it.copy(email = "test@example.com")
}

// 7. 实际场景
// 初始化 View
private fun setupViews() {
    recyclerView.apply {
        layoutManager = LinearLayoutManager(context)
        adapter = myAdapter
        addItemDecoration(DividerItemDecoration(context, VERTICAL))
    }
}

// 网络请求
suspend fun loadData() {
    val response = api.getData()
        .also { Log.d("API", "Response: $it") }
        .let {
            if (it.isSuccessful) it.body() else null
        }
        ?: run {
            showError()
            return
        }
    
    updateUI(response)
}

// 构建者模式
class DialogBuilder {
    var title: String = ""
    var message: String = ""
    var positiveButton: String = "OK"
    var negativeButton: String? = null
    
    fun build(): Dialog {
        return Dialog(title, message, positiveButton, negativeButton)
    }
}

fun dialog(block: DialogBuilder.() -> Unit): Dialog {
    return DialogBuilder().apply(block).build()
}

// 使用
dialog {
    title = "提示"
    message = "确定要删除吗?"
    positiveButton = "删除"
    negativeButton = "取消"
}.show()

综合实战示例

ViewModel 完整示例

kotlin
class UserViewModel(
    private val userRepository: UserRepository
) : ViewModel() {
    
    // StateFlow 状态
    private val _uiState = MutableStateFlow<UiState<User>>(UiState.Loading)
    val uiState: StateFlow<UiState<User>> = _uiState.asStateFlow()
    
    // SharedFlow 事件
    private val _events = MutableSharedFlow<UiEvent>()
    val events: SharedFlow<UiEvent> = _events.asSharedFlow()
    
    // 密封类
    sealed class UiState<out T> {
        object Loading : UiState<Nothing>()
        data class Success<T>(val data: T) : UiState<T>()
        data class Error(val message: String) : UiState<Nothing>()
    }
    
    sealed class UiEvent {
        object NavigateBack : UiEvent()
        data class ShowToast(val message: String) : UiEvent()
    }
    
    // 协程 + Flow
    fun loadUser(userId: String) {
        viewModelScope.launch {
            _uiState.value = UiState.Loading
            
            userRepository.getUserFlow(userId)
                .flowOn(Dispatchers.IO)
                .catch { e ->
                    _uiState.value = UiState.Error(e.message ?: "Error")
                    _events.emit(UiEvent.ShowToast("加载失败"))
                }
                .collect { user ->
                    _uiState.value = UiState.Success(user)
                }
        }
    }
    
    // 重试机制
    fun loadUserWithRetry(userId: String, maxRetries: Int = 3) {
        viewModelScope.launch {
            retry(maxRetries) {
                val user = userRepository.getUser(userId)
                _uiState.value = UiState.Success(user)
            }
        }
    }
    
    // 自定义重试
    private suspend inline fun retry(
        times: Int,
        initialDelay: Long = 100,
        maxDelay: Long = 1000,
        factor: Double = 2.0,
        block: suspend () -> Unit
    ) {
        var currentDelay = initialDelay
        repeat(times - 1) {
            try {
                block()
                return
            } catch (e: Exception) {
                // 记录错误
            }
            delay(currentDelay)
            currentDelay = (currentDelay * factor).toLong().coerceAtMost(maxDelay)
        }
        block()  // 最后一次
    }
    
    // 委托属性
    private val preferences: SharedPreferences by lazy {
        // 初始化
    }
    
    // 扩展函数使用
    private fun String.isValidEmail(): Boolean {
        return this.contains("@") && this.contains(".")
    }
}

面试速查表

知识点难度出现频率关键概念
空安全⭐⭐⭐⭐⭐⭐⭐?., ?:, !!, let
扩展函数⭐⭐⭐⭐⭐⭐⭐静态解析、不能访问私有成员
高阶函数⭐⭐⭐⭐⭐⭐⭐Lambda、函数类型、尾随 Lambda
协程⭐⭐⭐⭐⭐⭐⭐⭐⭐launch/async、作用域、Dispatcher
Flow⭐⭐⭐⭐⭐⭐⭐⭐StateFlowSharedFlow、操作符
委托⭐⭐⭐⭐⭐⭐by lazyDelegates
密封类⭐⭐⭐⭐⭐⭐⭐when exhaustive、状态管理
内联函数⭐⭐⭐⭐⭐⭐⭐inlinenoinlinecrossinline
泛型⭐⭐⭐⭐⭐⭐⭐in/out、PECS、reified
作用域函数⭐⭐⭐⭐⭐⭐⭐let/run/with/apply/also

📚 推荐资源

🎯 学习建议

  1. 先掌握基础语法(空安全、扩展函数)
  2. 深入理解协程和 Flow(面试必考)
  3. 熟练使用作用域函数
  4. 理解密封类在状态管理中的应用
  5. 实际项目中多练习泛型和内联函数

最后更新:2026-04-14