Android JetPack系列---LiveData

接着上一篇博客ViewModel,这一篇我们就来说一下一般配合ViewModel使用的LiveData

jetpack系列

第一篇:jetpack—Lifecycle的运用
第二篇:jetpack—ViewModel的了解
第三篇:jetpack—LiveData的使用
第四篇: JetPack系列—DataBinding的使用入门

什么是LiveData?

官方说明:LiveData 是一种可观察的数据存储器类。与常规的可观察类不同,LiveData 具有生命周期感知能力,意指它遵循其他应用组件(如 Activity、Fragment 或 Service)的生命周期。这种感知能力可确保 LiveData 仅更新处于活跃生命周期状态的应用组件观察者。如果观察者(由 Observer 类表示)的生命周期处于 STARTED 或 RESUMED 状态,则 LiveData 会认为该观察者处于活跃状态。LiveData 只会将更新通知给活跃的观察者。为观察 LiveData 对象而注册的非活跃观察者不会收到更改通知。

Android JetPack系列---LiveData_第1张图片

使用LiveData写一个示例参照官方文档上的步骤

1、创建 LiveData 的实例以存储某种类型的数据。这通常在 ViewModel 类中完成。那我们就先需要写一个viewModel,然后在创建LiveData实例。

class LiveDataViewModel : ViewModel() {
    private val data = MyData()

    private val liveData: MutableLiveData<MyData> by lazy {
        MutableLiveData<MyData>()
    }
    
    override fun onCleared() {
        super.onCleared()
    }
}

注意:
1、看源码可知LiveData是一个抽象类,我们就不能直接 使用,但是我们可以使用他的子类,MutableLiveData
2、确保更新界面的LiveData对象储存在ViewModel对象中

然后我们需要加入更新数据的一个方法setUserData,和获取数据的方法getUserData,在更新数据的setUserData中给livedata设置数据liveData.value = data

class LiveDataViewModel : ViewModel() {
    private val data = MyData()

    private val liveData: MutableLiveData<MyData> by lazy {
        MutableLiveData<MyData>()
    }
    //获取到myData实例
    fun getUserData(): LiveData<MyData> {
        return liveData
    }
	//更新数据的方法
    fun setUserData(str: String) {
        data.name = str
        liveData.value = data
    }

    override fun onCleared() {
        super.onCleared()
    }
}

注意:
Livedata提供给我们2个更新数据的方法,一个是PostValue 一个是setValue点击去看源码可以知道
postValue适用于非UI线程的异步线程
setValue是在UI线程中

我上面的示例并非异步线程中所以直接使用了setValue
Android JetPack系列---LiveData_第2张图片
2、创建可定义 onChanged() 方法的 Observer 对象,该方法可以控制当 LiveData 对象存储的数据更改时会发生什么。通常情况下,您可以在界面控制器(如 activity 或 fragment)中创建 Observer 对象。
就是在Activity中间我们需要创建一个观察者对数据进行观察

class MainActivity : AppCompatActivity() {
    private lateinit var start: TextView
    private lateinit var contentTv: TextView

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        start = findViewById(R.id.start)
        contentTv = findViewById(R.id.contentTv)

        //绑定viewModel
        val viewModel = ViewModelProvider(this)[LiveDataViewModel::class.java]
        //获取liveData
        val liveData = viewModel.getUserData()
        //liveData.observer()观察ViewModel中数据的变化
        liveData.observe(this, {
            contentTv.text =it.name
        })

        start.setOnClickListener {
            viewModel.setUserData("改变改变")
        }
    }
}

然后我们点击按钮改变一下viewModel中LiveData的值然后看下是否改变了。
Android JetPack系列---LiveData_第3张图片
从上面劣质的Gif可以看出LiveData的例子是已经成功了,并且因为ViewModel的原因,并不会因为屏幕旋转而导致数据丢失,如果对ViewModel有什么疑问的话可以看下我的上一篇,目录在文章的开头已经给出来了

接下来就简单的分析一下liveData.observe这个 方法看看他到底是怎么实现的 先看下源码

 @MainThread
    public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer) {
        assertMainThread("observe");
        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().addObserver(wrapper);
    }

1、首先点击observe可以看到这个方法需要一个LifecycleOwner ,我们上面传的是this进去,当前的activity,又因为我们前面再说LifeCycle的时候说过了CompatActivity是已经实现了LifecycleOwner,不是太清楚的话可以看下前面的LifeCycle那一篇,所以说LiveData就拥有了感知生命周期的能力。
2、if (owner.getLifecycle().getCurrentState() == DESTROYED) { return; }这句代码可以看出activity在生命周期结束的时候这个地方就直接return了不会在进行更新数据了。也就解决了有些地方因为activity生命周期结束而产生的内存溢出的问题。

接着往下看LifecycleBoundObserver wrapper = new LifecycleBoundObserver(owner, observer);
看下LifecycleBoundObserver 这个类

class LifecycleBoundObserver extends ObserverWrapper implements LifecycleEventObserver {
        @NonNull
        final LifecycleOwner mOwner;

        LifecycleBoundObserver(@NonNull LifecycleOwner owner, Observer<? super T> observer) {
            super(observer);
            mOwner = owner;
        }

        @Override
        boolean shouldBeActive() {
            return mOwner.getLifecycle().getCurrentState().isAtLeast(STARTED);
        }

        @Override
        public void onStateChanged(@NonNull LifecycleOwner source,
                @NonNull Lifecycle.Event event) {
            Lifecycle.State currentState = mOwner.getLifecycle().getCurrentState();
            if (currentState == DESTROYED) {
                removeObserver(mObserver);
                return;
            }
            Lifecycle.State prevState = null;
            while (prevState != currentState) {
                prevState = currentState;
                activeStateChanged(shouldBeActive());
                currentState = mOwner.getLifecycle().getCurrentState();
            }
        }

        @Override
        boolean isAttachedTo(LifecycleOwner owner) {
            return mOwner == owner;
        }

        @Override
        void detachObserver() {
            mOwner.getLifecycle().removeObserver(this);
        }
    }

1、可以看到 LifecycleBoundObserver 实现了LifecycleEventObserver 接口重写了onStateChanged这个方法就是说在生命周期状态改变的是时候会去调用。

Lifecycle.State currentState = mOwner.getLifecycle().getCurrentState();
            if (currentState == DESTROYED) {
                removeObserver(mObserver);
                return;
            }

然后获取了当前的生命周期,如果是当前生命周期是Destroyed,就移除掉了这个观察者就不在往下进行了,反之调用activeStateChanged(shouldBeActive());方法保持当前观察者,然后传进去了一个方法shouldBeActive()看下这个方法,返回的就是当前的生命周期的一个状态只有在start,resume,pause的时候才可以进行一个数据的更新

@Override
        boolean shouldBeActive() {
            return mOwner.getLifecycle().getCurrentState().isAtLeast(STARTED);
        }

上面就已经分析了一个LiveData 的一个工作的原理。

我们可以看到除了 liveData.observe,还有一个方法LiveData.observeForever
Android JetPack系列---LiveData_第4张图片
方法比对来看,用法都是一样的,但是observe传了一个当前的Activity,当前的Activity又是继承CompatActivity是已经实现了LifecycleOwner,进去相当于绑定了当前Activity的生命周期,从而让LiveData会跟随着Activity的生命周期, LiveData 会认为该观察者处于活跃状态。LiveData 只会将更新通知给活跃的观察者。
但是observeForever 并没有传递一个LifecycleOwner那就是说LiveData的数据发生变化时,无论页面处于什么状态,observeForever()都能收到通知。observeForever也不会随着Activity的销毁而停止对LiveData的观察,所以我们必须在使用完成的时候手动调用removeObserver()来停止对LiveData的观察,否者的话LiveData一直在激活的状态,你的Activity就不会被系统回收。

		liveData.observe(this, {
            contentTv.text =it.name
        })
        liveData.observeForever {
            contentTv.text =it.name
        }

LiveData基本上用到最多的也就是这些如果有什么说的不对的地方,还是麻烦提出来指正

你可能感兴趣的:(JetPack全家桶,android,jetpack,kotlin,LiveData)