Jetpack 系列 (三) — LiveData,大厂 Android 面试总结 + 详细解答
// 官方代码
class StockLiveData(symbol: String) : LiveData<BigDecimal>() {
private val stockManager: StockManager = StockManager(symbol)
private val listener = { price: BigDecimal ->
value = price
}
override fun onActive() {
stockManager.requestPriceUpdates(listener)
}
override fun onInactive() {
stockManager.removeUpdates(listener)
}
companion object {
private lateinit var sInstance: StockLiveData
@MainThread
fun get(symbol: String): StockLiveData {
sInstance = if (::sInstance.isInitialized) sInstance else StockLiveData(symbol)
return sInstance
}
}
}
观察
StockLiveData
StockLiveData.get(symbol).observe(viewLifecycleOwner, Observer<BigDecimal> { price: BigDecimal? ->
// Update the UI.
})
[](
)转换 LiveData
Lifecycle
软件包会提供Transformations
类,可以根据另一个实例的值返回不同的LiveData
实例,在将 LiveData 对象分派给观察者之前对存储在其中的值进行更改
map()
用于将实际包含数据的LiveData
和仅用于观察数据的LiveData
进行转换
//User.kt
data class User(var firstName: String, var lastName: String, var age: Int)
//HomeViewModel.kt
class HomeViewModel : ViewModel() {
private val _userLiveData = MutableLiveData<User>()
val userName: LiveData<String> = Transformations.map(_userLiveData) { user ->
"{user.lastName}"
}
fun updateTaps() {
_userLiveData.postValue(User("aa", "bb", 12))
}
}
switchMap()
对存储在LiveData
对象中的值应用函数
//HomeViewModel.kt
class HomeViewModel : ViewModel() {
private val _userIdLiveData = MutableLiveData<String>()
val user: LiveData<User> = Transformations.switchMap(_userIdLiveData) { userId ->
Repository.getUser(userId)
}
fun updateTaps() {
_userIdLiveData.postValue("cc")
}
}
// 测试
object Repository {
fun getUser(userId: String): LiveData<User> {
val liveData = MutableLiveData<User>()
liveData.value = User(userId, userId, 0)
return liveData
}
}
[](
)合并多个 LiveData 源
MediatorLiveData
允许合
并多个 LiveData 源,适用于一个观察者,多个被观察者
//HomeViewModel.kt
class HomeViewModel : ViewModel() {
private val _user1 = MutableLiveData<User>()
private val _user2 = MutableLiveData<User>()
var mediatorLiveData: MediatorLiveData<User> = MediatorLiveData()
init {
mediatorLiveData.addSource(_user1) {
mediatorLiveData.value = it
}
mediatorLiveData.addSource(_user2) {
mediatorLiveData.value = it
}
}
fun updateTaps() {
_user1.postValue(User("ll", "nn", 12))
_user2.postValue(User("xx", "bb", 12))
}
}
// HomeFragment.kt
...
private fun subscribeUI() {
observe(viewModel.mediatorLiveData, ::mediatorLiveDataUpdate)
}
private fun mediatorLiveDataUpdate(user: User?) {
Log.e("==========","$user")
}
[](
)相关知识点
知识点一:
postValue
和setValue
setValue
需要运行在主线程,postValue
不用
protected void postValue(T value) {
boolean postTask;
synchronized (mDataLock) {
postTask = mPendingData == NOT_SET;
mPendingData = value;
}
if (!postTask) {
return;
}
ArchTaskExecutor.getInstance().postToMainThread(mPostValueRunnable);
}
@MainThread
protected void setValue(T value) {
assertMainThread("setValue");
mVersion++;
mData = value;
dispatchingValue(null);
}
如果想进阶学习 jetpack 又缺少学习资料,而我正好薅到这本阿里十年技术专家联合打造“最新”《Jetpack 架构组件入门到精通》和《Jetpack 强化实战手册》,是你学习 Jetpack 的葵花宝典。
[](
)[点击此处蓝字免费获取](
)
[](
)《Jetpack 强化实战手册》
[](
)一、初识 ConstraintLayout 之实现登录页面
1.创建项目
2.沉浸式的布局
3.富文本
4.属性动画
[](
)二、Navigation 实践之实现 APP 主框架以及 Navigation 的相关介绍
1.搭建 Bottom Navigation Activity
2.导航界面跳转
3.Navigation 传值
4.Navigation 跳转动画
5.导航文件拆分
6.Deeplink 导航
[](
)三、使用 Coroutines, Retrofit, Moshi 实现网络数据请求
1.kotlin - Coroutine 协程
2.用协程和 Retrofit 实现网络请求
[](
)四、使用 TabLayout,ViewPager2 ,RecyclerView 实现实现歌单广场页面
1.ViewPager2
2.TabLayout
3.RecyclerView
4.网络数据请求和数据填充
5.优化界面
[](
)五、歌单页面 MVVM 架构改造及其 ViewModel 和 LiveData 的使用介绍
1.MVC 和 MVVM 介绍
2.修改歌单页面
[](
)六、Paging 实现加载更多和下拉刷新,错误后重新请求
1.Paging 的优势
2.Paging 实现分页加载更多
3.Paging 和 SwipRefreshLayout 组合实现下拉刷新
4.给 RecyclerView 添加加载状态的 Footer
5.发生网络错误后重试
6.帧动画
[](
)七、vlayout 嵌套横向 RecyclerView 和 Banner 实现主页的展示,自定义 Moshi 的 JsonAdapter
1.vlayout 架构分析
2.vlayout 布局介绍
3.基础工作准备
4.vlayout 实现轮播图
评论