【Android Jetpack高手日志】LiveData 从入门到精通

initiator = null;

} else {

for (Iterator<Map.Entry<Observer<? super T>, ObserverWrapper>> iterator =

mObservers.iteratorWithAdditions(); iterator.hasNext(); ) {

considerNotify(iterator.next().getValue());

if (mDispatchInvalidated) {

break;

}

}

}

} while (mDispatchInvalidated);

mDispatchingValue = false;

}

因为传入的dispatchingValue的参数为 null,所以我们进入considerNotify方法

private void considerNotify(ObserverWrapper observer) {

if (!observer.mActive) {

return;

}

// Check latest state b4 dispatch. Maybe it changed state but we didn’t get the event yet.

//

// we still first check observer.active to keep it as the entrance for events. So even if

// the observer moved to an active state, if we’ve not received that event, we better not

// notify for a more predictable notification order.

if (!observer.shouldBeActive()) {

observer.activeStateChanged(false);

return;

}

if (observer.mLastVersion >= mVersion) {

return;

}

observer.mLastVersion = mVersion;

observer.mObserver.onChanged((T) mData);

}

可以看到在最后一行,被观察者通知观察者进行onChanged数据变更,而我们的订阅是在 observe方法中

@MainThread

public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer) {

assertMainThread(“observe”);

//如果 LifecycleOwner 的 DESTROYED,return

if (owner.getLifecycle().getCurrentState() == DESTROYED) {

// ignore

return;

}

//包装类

LifecycleBoundObserver wrapper = new LifecycleBoundObserver(owner, observer);

ObserverWrapper existing = mObservers.putIfAbsent(observer, wrapper);

if (existing != null && !existing.isAttachedTo(owner)) {

throw new IllegalArgumentException(“Cannot add the same observer”

  • " with different lifecycles");

}

if (existing != null) {

return;

}

//添加观察者,owner.getLifecycle()的真正实现是 Activity 中的 LifecycleRegistry`(如果在Activity 中调用的话)。

owner.getLifecycle().addObserver(wrapper);

}

可以看到整个流程就是这么简单。就是简单的观察者模式的运用。不过 LiveData 还帮助我们自动处理的生命周期,防止内存泄漏。

要注意的是, LiveData#dispatchingValue除了在我们主动更新数据的时候会触发, 在我们的观察者状态变更(inactive->active)的时候, 也会通知到, 这就导致了LiveData必然支持粘性事件

setValue/postValue方法,是为了将数据通知到主线程,其中 postValue方法最终调用了setValue

protected void postValue(T value) {

boolean postTask;

synchronized (mDataLock) {

postTask = mPendingData == NOT_SET;

mPendingData = value;

}

if (!postTask) {

return;

}

ArchTaskExecutor.getInstance().postToMainThread(mPostValueRunnable); //发送到主线程

}

mPostValueRunnable 实例的内容如下:

private final Runnable mPostValueRunnable = new Runnable() {

@SuppressWarnings(“unchecked”)

@Override

public void run() {

Object newValue;

synchronized (mDataLock) {

newValue = mPendingData;

mPendingData = NOT_SET;

}

setValue((T) newValue); //最终还是调用了 setValue方法

}

};

使用 LiveData 的优势

确保界面符合数据状态

LiveData 遵循观察者模式。当底层数据发生变化时,LiveData 会通知 Observer 对象。您可以整合代码以在这些 Observer 对象中更新界面。这样一来,您无需在每次应用数据发生变化时更新界面,因为观察者会替您完成更新。

不会发生内存泄漏

观察者会绑定到 Lifecycle 对象,并在其关联的生命周期遭到销毁后进行自我清理。

不会因 Activity 停止而导致崩溃

如果观察者的生命周期处于非活跃状态(如返回栈中的 Activity),则它不会接收任何 LiveData 事件。

不再需要手动处理生命周期

界面组件只是观察相关数据,不会停止或恢复观察。LiveData 将自动管理所有这些操作,因为它在观察时可以感知相关的生命周期状态变化。

数据始终保持最新状态

如果生命周期变为非活跃状态,它会在再次变为活跃状态时接收最新的数据。例如,曾经在后台的 Activity 会在返回前台后立即接收最新的数据。

适当的配置更改

如果由于配置更改(如设备旋转)而重新创建了 Activity 或 Fragment,它会立即接收最新的可用数据。

共享资源

您可以使用单例模式扩展 LiveData 对象以封装系统服务,以便在应用中共享它们。LiveData 对象连接到系统服务一次,然后需要相应资源的任何观察者只需观察 LiveData 对象。如需了解详情,请参阅扩展 LiveData

基于 LiveData 的事件总线的实现(LiveDataBus)

可以看出, LiveData本身就已经可观测数据更新, 我们通过维护一张 eventName-LiveData 的哈希表, 就可以得到一个基础的事件总线

class LiveDataBus {

internal val liveDatas by lazy { mutableMapOf<String, LiveData<*>>() }

@Synchronized

private fun bus(channel: String): LiveData{

return liveDatas.getOrPut(channel){

LiveDataEvent(channel)

} as LiveData

}

fun with(channel: String): LiveData{

return bus(channel)

}

companion object{

private val INSTANCE by lazy { LiveDataBus() }

@JvmStatic

fun get() = INSTANCE

}

}

除了粘性事件以外,我们还需要非粘性事件的支持, 这里有两种做法。反射获取ObserverWrapper.mLastVersion, 在订阅的时候使得初始化的ObserverWrapper.mLastVersion等于LiveData.mVersion, 使得粘性消息无法通过实现;这里可以参考美团的文章:[Android消息总线的演进之路:用LiveDataBus替代RxBus、EventBus]。

还有一种做法是粘性消息最终会调到Observer#onChanged, 那么我们就干脆将其再进行一层包装, 内部维护实际的订阅消息数, 来判断是否要触发真正的onChanged方法,详细内容可以参考这篇文章

LiveData 的建议写法

在我自己的项目中,我通常使用该方式来定义LiveData,严格控制LiveData的权限,确保视图 Activity/Fragment 中只有该数据的访问权限,而将数据的修改权限严格控制在ViewModel中,参考自 github 上的一些优秀项目的写法。

//ViewModel.java

private val _cartCountLD: MutableLiveData = MutableLiveData()

val cartCountLD: LiveData

get() = _cartCountLD

private val _saveBirthdayLD: MutableLiveData = MutableLiveData()

val saveBirthdayLD: LiveData

get() = _saveBirthdayLD

灵魂拷问(在 Activity 的哪个几个生命周期修改 LiveData 值,能被观察者观察到)

前面说过数据变更的通知控制在生命周期活跃状态 STARTED、RESUMED,那么对应是哪几个生命周期呢?先来看看这段代码:

class MainActivity : AppCompatActivity() {

private var jetpackLiveData: MutableLiveData = MutableLiveData()

private val TAG = “================”

override fun onCreate(savedInstanceState: Bundle?) {

super.onCreate(savedInstanceState)

setContentView(R.layout.activity_main)

jetpackLiveData.observe(this,Observer {

Log.i(TAG, “observe value:”+it+" state:"+this.lifecycle.currentState)

})

Log.i(TAG, “onCreate: “+” state:”+this.lifecycle.currentState)

jetpackLiveData.value = “onCreate”

}

override fun onStart() {

super.onStart()

Log.i(TAG, “onStart: “+” state:”+this.lifecycle.currentState)

jetpackLiveData.value = “onStart”

}

override fun onResume() {

super.onResume()

Log.i(TAG, “onResume: “+” state:”+this.lifecycle.currentState)

jetpackLiveData.value = “onResume”

}

override fun onPause() {

super.onPause()

Log.i(TAG, “onPause: “+” state:”+this.lifecycle.currentState)

jetpackLiveData.value = “onPause”

}

override fun onStop() {

super.onStop()

Log.i(TAG, “onStop: “+” state:”+this.lifecycle.currentState)

jetpackLiveData.value = “onStop”

}

override fun onDestroy() {

super.onDestroy()

Log.i(TAG, “onDestroy: “+” state:”+this.lifecycle.currentState)

jetpackLiveData.value = “onDestroy”

}

}

启动界面并退出界面,观察到的日志是:

jetpackdemo I/================: onCreate: state:INITIALIZED

jetpackdemo I/================: onStart: state:CREATED

jetpackdemo I/================: observe value:onStart state:STARTED //STARTED 状态

jetpackdemo I/================: onResume: state:STARTED

jetpackdemo I/================: observe value:onResume state:STARTED //STARTED 状态

jetpackdemo I/================: onPause: state:STARTED

jetpackdemo I/================: observe value:onPause state:STARTED //STARTED 状态

jetpackdemo I/================: onStop: state:CREATED

jetpackdemo I/================: onDestroy: state:DESTROYED

结果是我们只能在onStart()、onResume()、onPause()这三个方法中,而且观察者观察到的状态都是 STARTED状态,注意,onStart 执行时是CREATED 状态,但是收到时是 STARTED 状态。那么问题又来了,RESUMED 状态呢,为什么没有呢

那么 RESUMED 状态呢我们应该怎么获取到呢?我们可以在 500ms 之后获取

override fun onResume() {

super.onResume()

Log.i(TAG, “onResume: “+” state:”+this.lifecycle.currentState)

jetpackLiveData.value = “onResume”

Handler().postDelayed(Runnable {

Log.i(TAG, “onResume: ======500 毫秒之后”+this.lifecycle.currentState)

},500)

}

获取到的日志如下:

jetpackdemo I/================: onResume: ======500 毫秒之后RESUMED

总结

如果非要用一句话来总结,LiveData是在Lifecycle 的帮助下,实现了生命周期管理的一致性,将数据变更的通知控制在生命周期活跃状态 STARTED、RESUMED(注意这是Lifecycle 中的 State)时进行通知,该通知成为数据的唯一可信来源,也就是视图获取数据的唯一入口。

文末


Jetpack Compose是谷歌在2019Google i/o大会上发布的新的库,是用于构建原生Android UI的现代工具包。他有强大的工具和直观的Kotlin API,简化并加速了Android上的UI开发。可以帮助开发者用更少更直观的代码创建View,还有更强大的功能,以及还能提高开发速度。

客观地讲,Compose 确实是一套比较难学的东西,因为它毕竟太新也太大了,它是一个完整的、全新的框架,确实让很多人感觉「学不动」,这也是个事实。

如果你是因为缺少学习资料,而我正好薅到这本谷歌内部大佬根据实战编写的《Jetpack Compose最全上手指南》,从入门到精通,教程通俗易懂,实例丰富,既有基础知识,也有进阶技能,能够帮助读者快速入门,是你学习Jetpack Compose的葵花宝典,快收藏起来!!!

由于篇幅原因,如有需要以下完整学习笔记PDF,可以点击我的GitHub免费下载获取!

第一章 初识 Jetpack Compose

1. 为什么我们需要一个新的UI 工具?

2. Jetpack Compose的着重点

  • 加速开发

  • 强大的UI工具

  • 直观的Kotlin API

3. API 设计

4. Compose API 的原则

  • 一切都是函数

  • 顶层函数(Top-level function)

  • 组合优于继承

  • 信任单一来源

5. 深入了解Compose

  • Core

  • Foundation

  • Material

  1. 插槽API

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数初中级安卓工程师,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年最新Android移动开发全套学习资料》送给大家,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
img
img
img
img

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频
如果你觉得这些内容对你有帮助,可以添加下面V无偿领取!(备注Android)
img

学习福利

【Android 详细知识点思维脑图(技能树)】

其实Android开发的知识点就那么多,面试问来问去还是那么点东西。所以面试没有其他的诀窍,只看你对这些知识点准备的充分程度。so,出去面试时先看看自己复习到了哪个阶段就好。

虽然 Android 没有前几年火热了,已经过去了会四大组件就能找到高薪职位的时代了。这只能说明 Android 中级以下的岗位饱和了,现在高级工程师还是比较缺少的,很多高级职位给的薪资真的特别高(钱多也不一定能找到合适的),所以努力让自己成为高级工程师才是最重要的。

这里附上上述的面试题相关的几十套字节跳动,京东,小米,腾讯、头条、阿里、美团等公司19年的面试题。把技术点整理成了视频和PDF(实际上比预期多花了不少精力),包含知识脉络 + 诸多细节。

由于篇幅有限,这里以图片的形式给大家展示一小部分。

详细整理在GitHub可以见;

Android架构视频+BAT面试专题PDF+学习笔记

网上学习 Android的资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。希望这份系统化的技术体系对大家有一个方向参考。

学习福利

【Android 详细知识点思维脑图(技能树)】

[外链图片转存中…(img-pQTVOK3N-1710852981460)]

其实Android开发的知识点就那么多,面试问来问去还是那么点东西。所以面试没有其他的诀窍,只看你对这些知识点准备的充分程度。so,出去面试时先看看自己复习到了哪个阶段就好。

虽然 Android 没有前几年火热了,已经过去了会四大组件就能找到高薪职位的时代了。这只能说明 Android 中级以下的岗位饱和了,现在高级工程师还是比较缺少的,很多高级职位给的薪资真的特别高(钱多也不一定能找到合适的),所以努力让自己成为高级工程师才是最重要的。

这里附上上述的面试题相关的几十套字节跳动,京东,小米,腾讯、头条、阿里、美团等公司19年的面试题。把技术点整理成了视频和PDF(实际上比预期多花了不少精力),包含知识脉络 + 诸多细节。

由于篇幅有限,这里以图片的形式给大家展示一小部分。

[外链图片转存中…(img-zEAU6fRu-1710852981460)]

详细整理在GitHub可以见;

Android架构视频+BAT面试专题PDF+学习笔记

网上学习 Android的资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。希望这份系统化的技术体系对大家有一个方向参考。

  • 7
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: Jetpack是一套基于Android开发语言Kotlin的组件库,目的是帮助Android开发者快速构建健壮的、高效的应用程序。Jetpack架构组件从入门到精通是一本介绍Jetpack组件库的电子书,其内容向读者提供了Jetpack组件库的最基础的知识体系,以及对组件库的更高阶的实践知识和技能分享。 在读者学习这本电子书时,首先会学习到基本的Jetpack概念,并了解到如何使用各种工具来实现底层代码、布局和资源文件的编写。同时,电子书重点讲解了Jetpack组件库中最常用的组件,比如ViewModel、LiveData、Room、WorkManager等,它们各自的功能和用法,让读者熟知Jetpack组件的基本运作原理。读者还会学习如何将这些组件综合使用,以构造真正的应用程序。在内容的后半部分,电子书重点讲解了Jetpack在架构层面的设计,以及如何更有效的使用和管理组件库。 总之,Jetpack架构组件从入门到精通这本电子书非常适合想要学习Jetpack组件库的Android初学者和有一定开发经验的开发者,能够帮助他们快速掌握Jetpack组件库,以及提高软件的可扩展性和有效性。 ### 回答2: Jetpack架构组件是一组Android软件组件和库,通过这些组件和库,开发者可以更加轻松地开发应用程序,并提供高质量的用户体验。Jetpack架构组件包括众多不同的组件和库,这些组件和库都具有不同的用途和功能。对于开发者来说,学习Jetpack架构组件是非常重要的。 《jetpack架构组件从入门到精通 pdf》是一份针对Jetpack架构组件的学习资料。它是可以帮助开发者更好地理解和掌握Jetpack架构组件的重要手册。通过这份PDF文档,开发者可以学习到Jetpack架构组件的基本概念、用途和功能,并了解如何将这些组件和库应用到他们的应用程序开发中。 这份PDF文档涵盖了Jetpack架构组件的多个方面,包括ViewModel、LiveDataData Binding、Room、Navigation、WorkManager等等。每个章节都包含了详细的介绍和具体的用例,从而帮助开发者更好地理解每个组件和库的用途和功能。 无论是初学者还是经验丰富的开发者,都可以从这份PDF文档中获益。它可以帮助初学者更轻松地入门Jetpack架构组件,并提供了有用的工具和技巧。对于经验丰富的开发者来说,这份PDF文档可以帮助他们更深入地了解Jetpack架构组件,并提供了一些高级技术和策略,以优化应用程序性能和用户体验。 总之,Jetpack架构组件从入门到精通的PDF文档是一份非常有价值的资源,它可以帮助开发者更好地理解和掌握Jetpack架构组件,从而更加轻松地开发高质量的Android应用程序。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值