android-patterns

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Android Development Patterns

Android开发模式

Modern Android patterns with Kotlin, coroutines, and functional programming.
基于Kotlin、协程和函数式编程的现代Android开发模式。

Kotlin Idioms

Kotlin惯用写法

Immutability

不可变性

kotlin
// ✅ Prefer val over var
val name: String = "John"

// ✅ Immutable collections
val items: List<Item> = listOf(item1, item2)

// ✅ Data class with copy
data class User(val id: String, val name: String)
val updatedUser = user.copy(name = "Jane")
kotlin
// ✅ 优先使用val而非var
val name: String = "John"

// ✅ 不可变集合
val items: List<Item> = listOf(item1, item2)

// ✅ 带copy方法的数据类
data class User(val id: String, val name: String)
val updatedUser = user.copy(name = "Jane")

Null Safety

空安全

kotlin
// ✅ Safe call
val length = name?.length

// ✅ Elvis operator
val name = nullableName ?: "Unknown"

// ✅ let for null checks
nullableUser?.let { user ->
    processUser(user)
}

// ✅ Early return with null check
fun processUser(user: User?) {
    user ?: return
    // user is smart-cast to non-null
}
kotlin
// ✅ 安全调用
val length = name?.length

// ✅ Elvis操作符
val name = nullableName ?: "Unknown"

// ✅ 使用let进行空检查
nullableUser?.let { user ->
    processUser(user)
}

// ✅ 空检查后提前返回
fun processUser(user: User?) {
    user ?: return
    // user会被智能转换为非空类型
}

Scope Functions

作用域函数

kotlin
// let - Transform and return
val result = nullable?.let { transform(it) }

// run - Configure and return result
val result = service.run {
    configure()
    execute()
}

// with - Operate on object
with(binding) {
    title.text = "Title"
    subtitle.text = "Subtitle"
}

// apply - Configure and return self
val user = User().apply {
    name = "John"
    email = "john@example.com"
}

// also - Side effects, return self
val user = User().also {
    logger.log("Created user: ${it.id}")
}
kotlin
// let - 转换并返回结果
val result = nullable?.let { transform(it) }

// run - 配置并返回结果
val result = service.run {
    configure()
    execute()
}

// with - 对对象进行操作
with(binding) {
    title.text = "Title"
    subtitle.text = "Subtitle"
}

// apply - 配置并返回自身
val user = User().apply {
    name = "John"
    email = "john@example.com"
}

// also - 执行副作用并返回自身
val user = User().also {
    logger.log("Created user: ${it.id}")
}

Extensions

扩展

kotlin
// ✅ Extension functions
fun String.isValidEmail(): Boolean {
    return android.util.Patterns.EMAIL_ADDRESS.matcher(this).matches()
}

// ✅ Extension properties
val Context.screenWidth: Int
    get() = resources.displayMetrics.widthPixels

// Usage
if (email.isValidEmail()) { ... }
val width = context.screenWidth
kotlin
// ✅ 扩展函数
fun String.isValidEmail(): Boolean {
    return android.util.Patterns.EMAIL_ADDRESS.matcher(this).matches()
}

// ✅ 扩展属性
val Context.screenWidth: Int
    get() = resources.displayMetrics.widthPixels

// 使用示例
if (email.isValidEmail()) { ... }
val width = context.screenWidth

Lifecycle Patterns

生命周期模式

ViewModel

ViewModel

kotlin
class HomeViewModel(
    private val repository: HomeRepository,
    savedStateHandle: SavedStateHandle
) : ViewModel() {

    private val _state = MutableStateFlow(HomeState())
    val state: StateFlow<HomeState> = _state.asStateFlow()
    
    init {
        loadData()
    }
    
    private fun loadData() {
        viewModelScope.launch {
            _state.update { it.copy(isLoading = true) }
            
            repository.getItems()
                .onSuccess { items -> _state.update { it.copy(items = items, isLoading = false) } }
                .onFailure { error -> _state.update { it.copy(error = error.message, isLoading = false) } }
        }
    }
}
kotlin
class HomeViewModel(
    private val repository: HomeRepository,
    savedStateHandle: SavedStateHandle
) : ViewModel() {

    private val _state = MutableStateFlow(HomeState())
    val state: StateFlow<HomeState> = _state.asStateFlow()
    
    init {
        loadData()
    }
    
    private fun loadData() {
        viewModelScope.launch {
            _state.update { it.copy(isLoading = true) }
            
            repository.getItems()
                .onSuccess { items -> _state.update { it.copy(items = items, isLoading = false) } }
                .onFailure { error -> _state.update { it.copy(error = error.message, isLoading = false) } }
        }
    }
}

Lifecycle-aware Collection

感知生命周期的收集

kotlin
@Composable
fun HomeScreen(viewModel: HomeViewModel = koinViewModel()) {
    val state by viewModel.state.collectAsStateWithLifecycle()
    
    HomeContent(state = state)
}
kotlin
@Composable
fun HomeScreen(viewModel: HomeViewModel = koinViewModel()) {
    val state by viewModel.state.collectAsStateWithLifecycle()
    
    HomeContent(state = state)
}

Functional Patterns

函数式模式

Result Type

结果类型

kotlin
// ✅ Use Result for operations that can fail
suspend fun fetchUser(id: String): Result<User> = runCatching {
    api.getUser(id).toDomain()
}

// ✅ Chain operations
repository.fetchUser(id)
    .map { it.profile }
    .mapCatching { decryptProfile(it) }
    .onSuccess { displayProfile(it) }
    .onFailure { showError(it) }
kotlin
// ✅ 对可能失败的操作使用Result类型
suspend fun fetchUser(id: String): Result<User> = runCatching {
    api.getUser(id).toDomain()
}

// ✅ 链式操作
repository.fetchUser(id)
    .map { it.profile }
    .mapCatching { decryptProfile(it) }
    .onSuccess { displayProfile(it) }
    .onFailure { showError(it) }

Higher-Order Functions

高阶函数

kotlin
// ✅ Pass functions as parameters
fun <T> retry(
    times: Int,
    block: suspend () -> T
): T {
    repeat(times - 1) {
        try { return block() }
        catch (e: Exception) { delay(1000) }
    }
    return block() // Last attempt
}

// Usage
val result = retry(3) { api.fetchData() }
kotlin
// ✅ 将函数作为参数传递
fun <T> retry(
    times: Int,
    block: suspend () -> T
): T {
    repeat(times - 1) {
        try { return block() }
        catch (e: Exception) { delay(1000) }
    }
    return block() // 最后一次尝试
}

// 使用示例
val result = retry(3) { api.fetchData() }

Sealed Classes

密封类

kotlin
sealed interface UiState<out T> {
    data object Loading : UiState<Nothing>
    data class Success<T>(val data: T) : UiState<T>
    data class Error(val message: String) : UiState<Nothing>
}

// Exhaustive when
when (state) {
    is UiState.Loading -> LoadingIndicator()
    is UiState.Success -> Content(state.data)
    is UiState.Error -> ErrorMessage(state.message)
}
kotlin
sealed interface UiState<out T> {
    data object Loading : UiState<Nothing>
    data class Success<T>(val data: T) : UiState<T>
    data class Error(val message: String) : UiState<Nothing>
}

// 穷尽式when表达式
when (state) {
    is UiState.Loading -> LoadingIndicator()
    is UiState.Success -> Content(state.data)
    is UiState.Error -> ErrorMessage(state.message)
}

Resource Management

资源管理

Context Extensions

Context扩展

kotlin
fun Context.dp(value: Int): Int = 
    (value * resources.displayMetrics.density).toInt()

fun Context.showToast(message: String) {
    Toast.makeText(this, message, Toast.LENGTH_SHORT).show()
}
kotlin
fun Context.dp(value: Int): Int = 
    (value * resources.displayMetrics.density).toInt()

fun Context.showToast(message: String) {
    Toast.makeText(this, message, Toast.LENGTH_SHORT).show()
}

String Resources

字符串资源

kotlin
// strings.xml
<string name="welcome_message">Welcome, %1$s!</string>

// Usage
stringResource(R.string.welcome_message, userName)

Remember: Kotlin is concise. Embrace its idioms for cleaner, safer code.
kotlin
// strings.xml
<string name="welcome_message">Welcome, %1$s!</string>

// 使用示例
stringResource(R.string.welcome_message, userName)

记住:Kotlin语法简洁。拥抱其惯用写法,编写更简洁、更安全的代码。