Android 之 Jetpack - LiveData+ViewModel

下面是一个完整的 Android LiveData 使用示例,结合 ViewModel 实现生命周期感知的数据更新,包含核心逻辑和详细注释:

1. ​​添加依赖 (build.gradle)​

dependencies {
    implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.6.1"
    implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.6.1"
}

2. ​​数据模型 (User.kt)​

data class User(
    val name: String,
    val age: Int
)

3. ​​ViewModel (UserViewModel.kt)​

import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch

class UserViewModel : ViewModel() {
    // 私有可变数据,仅ViewModel可修改
    private val _userLiveData = MutableLiveData<User>()
    // 对外暴露不可变LiveData,供UI观察
    val userLiveData: LiveData<User> get() = _userLiveData

    private val _loadingState = MutableLiveData<Boolean>()
    val loadingState: LiveData<Boolean> = _loadingState

    // 模拟网络请求
    fun fetchUser() {
        viewModelScope.launch {
            _loadingState.value = true
            delay(2000) // 模拟网络延迟
            _userLiveData.value = User("John Doe", 30) // 主线程更新
            _loadingState.value = false
        }
    }

    // 直接更新数据(主线程)
    fun updateName(newName: String) {
        _userLiveData.value = _userLiveData.value?.copy(name = newName)
    }
}

4. ​​Activity (UserActivity.kt)​

import android.os.Bundle
import android.widget.Button
import android.widget.ProgressBar
import android.widget.TextView
import androidx.activity.viewModels
import androidx.appcompat.app.AppCompatActivity
import androidx.lifecycle.Observer

class UserActivity : AppCompatActivity() {
    private val viewModel: UserViewModel by viewModels() // 获取ViewModel实例

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_user)

        val tvName = findViewById<TextView>(R.id.tv_name)
        val tvAge = findViewById<TextView>(R.id.tv_age)
        val progressBar = findViewById<ProgressBar>(R.id.progress_bar)
        val btnRefresh = findViewById<Button>(R.id.btn_refresh)

        // 观察用户数据变化
        viewModel.userLiveData.observe(this) { user ->
            tvName.text = "Name: ${user.name}"
            tvAge.text = "Age: ${user.age}"
        }

        // 观察加载状态
        viewModel.loadingState.observe(this) { isLoading ->
            progressBar.visibility = if (isLoading) View.VISIBLE else View.GONE
        }

        // 按钮点击更新数据
        btnRefresh.setOnClickListener {
            viewModel.fetchUser() // 触发数据刷新
        }

        // 模拟实时更新
        findViewById<Button>(R.id.btn_update).setOnClickListener {
            viewModel.updateName("Jane Smith") // 主线程直接更新
        }
    }
}

 5. ​​布局文件 (activity_user.xml)​

<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:padding="16dp">

    <ProgressBar
        android:id="@+id/progress_bar"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:visibility="gone"/>

    <TextView
        android:id="@+id/tv_name"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textSize="18sp"
        android:text="Name: -"/>

    <TextView
        android:id="@+id/tv_age"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textSize="18sp"
        android:text="Age: -"/>

    <Button
        android:id="@+id/btn_refresh"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Refresh Data"/>

    <Button
        android:id="@+id/btn_update"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Update Name"/>
</LinearLayout>

关键机制解析​

  1. ​生命周期感知​

    • 当 UserActivity 进入后台时,LiveData 自动暂停更新,避免无效 UI 操作。
    • 页面销毁时自动解除观察者绑定,防止内存泄漏。
  2. ​线程安全​

    • postValue() 用于后台线程更新(如 fetchUser() 中的协程)。
    • setValue() 用于主线程更新(如 updateName())。
  3. ​数据封装​

    • 对外暴露 LiveData<User>(只读),内部使用 MutableLiveData(可变),保证数据安全性。
  4. ​状态管理​

    • 通过 loadingState 分离数据与状态,优化用户体验
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值