Lifecycle + LiveData + ViewModel源码解析

一 简介

Lifecycle 是 Jetpack 整个家族体系内最为基础的内容之一,为上层的LiveData、ViewModel等等更上层的组件提供监听 Activity、Fragment、Service、甚至 Process 的生命周期变化的统一方式。
LiveData 是 Jetpack 家族的一种响应式开发框架,类似框架有还RxJava等。以数据驱动的方式更新UI,并且由于其基于Livecycle,能够感知组件生命周期变化,只会更新活跃的组件的状态,并在组件销毁时能自动解除对该组件的监听。
ViewModel: Activity或Fragment支持以数据以ViewModel的形式存储在内部,于是ViewModel常常作为组件相关的多个LiveData的存储载体。ViewModel 里面的数据不会因为屏幕的旋转或者其他配置(比如切换到多窗口模式)而丢失。

二 Lifecycle

前边提到Lifecycle提供了程序监听组件(后边统一以Activity组件来展开介绍)的接口

public abstract class Lifecycle {

    public abstract void addObserver(@NonNull LifecycleObserver observer);

    public abstract void removeObserver(@NonNull LifecycleObserver observer);
}

程序员可以自定义实现LifecycleObserver来监听activity的生命周期

Lifecycle是一个抽象类,它的唯一实现类为LifecycleRegister。查看FeagmentActivity的getLifecycle()方法,返回的就是LifecycleRegister的对象

public Lifecycle getLifecycle() {
    // Instead of directly using the Activity's Lifecycle, we
    // use a LifecycleRegistry that is nested exactly outside of
    // when Fragments get their lifecycle changed
    // TODO(b/127528777) Drive Fragment Lifecycle with LifecycleObserver
    return mFragmentLifecycleRegistry;
}

LifecycleRegister内部的mObserverMap字段保存了所有监听该Activity(LifecycleOwner)的观察者

private FastSafeIterableMap<LifecycleObserver, ObserverWithState> mObserverMap =
        new FastSafeIterableMap<>();

下边分析下Lifecycle如何完成监听activity的生命周期变化:
以FragmentActivity的onCreate()方法为入口:

protected void onCreate(@Nullable Bundle savedInstanceState) {
   // ...

    super.onCreate(savedInstanceState);
    mFragmentLifecycleRegistry.handleLifecycleEvent(Lifecycle.Event.ON_CREATE);

    // ...
}

可以看到会调用LifecycleRegister的handlerLifecycleEvent()方法。
给出handlerLifecycleEvent()的调用链:
handlerLifecycleEvent() -> moveToState() -> sync() -> forwardPass() -> LifecycleEventObserver.dispatchEvent() -> LifecycleEventObserver.onStateChanged()

  • LifecycleRegister的handlerLifecycleEvent(Lifecycle.Event)传递一个Lifecycle.Event,并根据这个Event对象更改自己的state。
  • moveToState()修改LifecycleRegister的 state,调用sync()
  • sync()负责通知observer,(以forwardPass()为例)
  • forwardPass()遍历所有的Observer,一一通知
  • LifecycleEventObserver.dispatchEvent()是单个observer对通知进行处理
  • 最后触发我们LifecycleEventObserver.onStateChanged()来完成回调。
    注:LifecycleEventObserver是LifecycleObserver的一个子接口,其onStateChanged()感知被监听组件的所有生命周期变化

三 LiveData

LiveData的简单使用这边不做介绍,需先了解其简单实用再向下看。
LiveData可以认为是我们要存储的对象的一个封装

public abstract class LiveData<T> {
    public T getValue() {
        Object data = mData;
        if (data != NOT_SET) {
            //noinspection unchecked
            return (T) data;
        }
        return null;
    }

    protected void setValue(T value) {
        assertMainThread("setValue");
        mVersion++;
        mData = value;
        dispatchingValue(null);
    }
}

通过其getValue()和和setValue()方法可以看出这一点。
既然将我们存储的对象封装起来,必然要有其好处。使用LiveData封装起来数据的好处也即是前边提到的 其封装的数据的变化能够被监听(数据驱动视图的基础),并且能够感知组件生命周期。

3.1 LiveData如何实现感知组件生命周期

和前边的Lifecycle一样,LiveData也能被Observer监听。不过LiveData的Observer的类型为androidx.lifecycle.Observer,其接口只有一个方法,onChanged(),方法在LiveData所封装的数据变化时被回调。

public interface Observer<T> {
    /**
     * Called when the data is changed.
     * @param t  The new data
     */
    void onChanged(T t);
}

一个LiveData能被多个Observer监听,其内部保存了所有监听该LiveData数据的观察者(可以看到类似于前边提到LifecycleRegister)

private SafeIterableMap<Observer<? super T>, ObserverWrapper> mObservers =
        new SafeIterableMap<>();

从LiveData.observe()方法入手

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);
}

通过

LifecycleBoundObserver wrapper = new LifecycleBoundObserver(owner, observer);

这句代码可以看到,LiveData将owner(LiveData内部数据所在的组件)和observer包装成了一个LifecycleBoundObserver对象(warpper)。然后将这个warpper保存在内部的mObservers中

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

最后给组件的Lifecyle也注册此观察者

owner.getLifecycle().addObserver(wrapper);

先来分析下LifecycleBoundObserver这个类。

class LifecycleBoundObserver extends ObserverWrapper implements GenericLifecycleObserver {

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

}

LifecycleBoundObserver继承自ObserverWarpper、实现了GenericLifecycleObserver接口,GenericLifecycleObserver是LifecycleEventObserver的子接口,所以其实现LifecycleEventObserver的onStateChanged()方法,具有了监听组件生命周期的能力。
查看onStateChanged()方法的逻辑,当组件(LifecycleOwner)的状态变为DESTROYED时,执行removeObserver(),自动解绑当前观察者。自此可以看到LiveData内部能够感知组件生命周期,能够自动解绑观察者,避免内存泄漏。

3.2 LiveData如何实现监听数据的变化

既然要看LiveData如何实现监听数据的变化,首先就得看看如何改变LiveData的数据,LiveData.setValue()
从LiveData.setValue()方法入手

protected void setValue(T value) {
    assertMainThread("setValue");
    mVersion++;
    mData = value;
    dispatchingValue(null);
}

接着进入dispatchingValue()方法

void dispatchingValue(@Nullable ObserverWrapper initiator) {
    if (mDispatchingValue) {
        mDispatchInvalidated = true;
        return;
    }
    mDispatchingValue = true;
    do {
        mDispatchInvalidated = false;
        if (initiator != null) {
            considerNotify(initiator);
            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;
}

由于传入的参数initiator为null,我们直接看initiator ==null 的分支。会遍历该LiveData的所有观察者,逐一调用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;
    //noinspection unchecked
    observer.mObserver.onChanged((T) mData);
}

可以看到最后一句

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

回调了LiveData观察者的onChanged()方法,我们即可以在此回调中更新与该数据绑定的相关UI。

四 ViewModel

4.1 ViewModelStore

说到ViewModel首先来看看Activity对ViewModel的支持。

public class ComponentActivity extends androidx.core.app.ComponentActivity implements ViewModelStoreOwner{
    private ViewModelStore mViewModelStore;
}

ComponentActivity实现了ViewModelOwner接口,并内部持有ViewModelStore对象
查看ViewModelStore对象

public class ViewModelStore {

    private final HashMap<String, ViewModel> mMap = new HashMap<>();

    final void put(String key, ViewModel viewModel) {
        ViewModel oldViewModel = mMap.put(key, viewModel);
        if (oldViewModel != null) {
            oldViewModel.onCleared();
        }
    }

    final ViewModel get(String key) {
        return mMap.get(key);
    }

    Set<String> keys() {
        return new HashSet<>(mMap.keySet());
    }

    /**
     *  Clears internal storage and notifies ViewModels that they are no longer used.
     */
    public final void clear() {
        for (ViewModel vm : mMap.values()) {
            vm.clear();
        }
        mMap.clear();
    }
}

可以看到ViewModelStore对象内部简单通过一个HashMap保存了与此Activity关联的所有ViewModel。

4.2 ViewModelProviders.of(activity).get(ViewModel.class)

ViewModelProviders.of(activity).get(ViewModel.class);

此调用用于获取同一个activity内部的的ViewModel对象,可以方便的实现在该activity的任何组件内获得该activity的共享的ViewModel,进而可以通过此特性很方便实现activty内部的组件通信。
源码也相对简单

ViewModelProviders.of(activity)

会获得一个ViewModelProvider对象,

ViewModelProvider.get(ViewModel.class);

会查找该acitvity的viewModelStore对象找到对应的ViewModel

一个ViewModel相关的疑问解答

  1. ViewModel的作用是什么,看起来单独的LiveData已经就拥有了根据数据变化自动更新UI的功能,并也能完成在LifecycleOwner销毁时自动removeObserver的功能。难道仅仅是MVVM的一个部分,看起来继承ViewModel的意义就不大了
    a. ViewModel提供了一种访问数据的统一方式,在整个Activity内部的任何组件都能直接获取整个Activity的共享数据。
ViewModelProviders.of(getActivity()).get(XXXModel.class)

也可进一步理解为Activity提供了ViewModelStore而没有提供LiveDataStore,所以才导致要使用ViewModel
b. Activity有对ViewModel的恢复机制,在Activity销毁重建后仍然可以获得原来的ViewModel内容

相关博客参考

Lifecycle源码解析:https://juejin.im/post/6847902220755992589#heading-13
LiveData源码解析:https://juejin.im/post/6844903796657782791
ViewModel源码解析:https://juejin.im/post/6844904169401221134

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,下面是一个简单的示例: 首先,在build.gradle文件中添加以下依赖项: ```groovy // ViewModel and LiveData implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0' // Data Binding implementation 'androidx.databinding:databinding-runtime:4.0.1' ``` 接下来,创建一个名为MainActivity的Activity,并在其布局文件中添加两个Fragment的占位符: activity_main.xml: ```xml <layout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto"> <FrameLayout android:id="@+id/container" android:layout_width="match_parent" android:layout_height="match_parent"/> </layout> ``` MainActivity.java: ```java public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); ActivityMainBinding binding = DataBindingUtil.setContentView(this, R.layout.activity_main); // 加载第一个Fragment getSupportFragmentManager().beginTransaction() .replace(R.id.container, new FirstFragment()) .commit(); } } ``` 接下来,创建一个名为FirstFragment的Fragment,并在其布局文件中使用DataBinding绑定数据: first_fragment.xml: ```xml <layout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto"> <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <TextView android:id="@+id/textView" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@{viewModel.text}" /> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Next" android:onClick="@{viewModel::onNextClicked}" /> </LinearLayout> </layout> ``` FirstFragment.java: ```java public class FirstFragment extends Fragment { private FirstViewModel viewModel; @Nullable @Override public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { // 使用DataBinding绑定布局文件 FirstFragmentBinding binding = DataBindingUtil.inflate(inflater, R.layout.first_fragment, container, false); // 创建ViewModel实例 viewModel = ViewModelProviders.of(this).get(FirstViewModel.class); // 将ViewModel与布局文件中的变量绑定 binding.setViewModel(viewModel); // 设置LifecycleOwner,以便LiveData知道何时更新UI binding.setLifecycleOwner(this); return binding.getRoot(); } } ``` 下面是FirstViewModel.java: ```java public class FirstViewModel extends ViewModel { private MutableLiveData<String> textLiveData = new MutableLiveData<>(); public FirstViewModel() { // 初始化LiveData的默认值 textLiveData.setValue("Hello, World!"); } public LiveData<String> getText() { return textLiveData; } public void onNextClicked() { // 更新LiveData的值 textLiveData.setValue("Next Clicked!"); } } ``` 最后,创建另一个名为SecondFragment的Fragment,并在MainActivity中添加一个方法来加载它: second_fragment.xml: ```xml <layout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto"> <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <TextView android:id="@+id/textView" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@{viewModel.text}" /> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Previous" android:onClick="@{viewModel::onPreviousClicked}" /> </LinearLayout> </layout> ``` SecondFragment.java: ```java public class SecondFragment extends Fragment { private SecondViewModel viewModel; @Nullable @Override public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { // 使用DataBinding绑定布局文件 SecondFragmentBinding binding = DataBindingUtil.inflate(inflater, R.layout.second_fragment, container, false); // 创建ViewModel实例 viewModel = ViewModelProviders.of(this).get(SecondViewModel.class); // 将ViewModel与布局文件中的变量绑定 binding.setViewModel(viewModel); // 设置LifecycleOwner,以便LiveData知道何时更新UI binding.setLifecycleOwner(this); return binding.getRoot(); } } ``` 下面是SecondViewModel.java: ```java public class SecondViewModel extends ViewModel { private MutableLiveData<String> textLiveData = new MutableLiveData<>(); public SecondViewModel() { // 初始化LiveData的默认值 textLiveData.setValue("Goodbye, World!"); } public LiveData<String> getText() { return textLiveData; } public void onPreviousClicked() { // 更新LiveData的值 textLiveData.setValue("Previous Clicked!"); } } ``` 最后,在MainActivity中添加一个方法来加载SecondFragment: ```java private void loadSecondFragment() { getSupportFragmentManager().beginTransaction() .replace(R.id.container, new SecondFragment()) .commit(); } ``` 现在,你的MVVM Android项目就完成了!你可以使用LiveDataViewModel来管理数据,并使用DataBinding将数据绑定到UI上。Lifecycle组件可确保UI在活动和片段之间正确地进行管理。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值