下面是一个完整的 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>
关键机制解析
-
生命周期感知
- 当
UserActivity进入后台时,LiveData 自动暂停更新,避免无效 UI 操作。 - 页面销毁时自动解除观察者绑定,防止内存泄漏。
- 当
-
线程安全
postValue()用于后台线程更新(如fetchUser()中的协程)。setValue()用于主线程更新(如updateName())。
-
数据封装
- 对外暴露
LiveData<User>(只读),内部使用MutableLiveData(可变),保证数据安全性。
- 对外暴露
-
状态管理
- 通过
loadingState分离数据与状态,优化用户体验
- 通过
1418

被折叠的 条评论
为什么被折叠?



