Jetpack 组件 LiveData + viewModel 使用分析

Jetpack 组件 LiveData + viewModel 使用分析

1、LiveData 简介

LiveData 是一个可观察对象的持有者,与常规的可观察对象不同,liveData 是生命周期感知的,这意味着它尊重其他应该用程序组件(如 activity,fragment ,service)这种意识确保LiveData只更新处于活动生命周期状态的应用程序组件观察者

LiveData 认为一个观察者的生命周期处于启动或恢复状态,那么这个观察者(由观察类表示)就处于活动状态

LiveData 只向活动的观察者通知更新。注册来监听liveData对象的非活动观察者不会收到关于更改的通知

您可以注册一个与实现LifeCycleOwner 接口的对象配对的观察者。当相应的生命周期对象的状态更改为销毁时,这种关系允许删除观察者。这对于活动和片段特别有用,因为他们可以安全地观察LiveData对象,而不用担心内存泄漏——当activity 和fragment 的生命周期被破坏时,他们会立即取消订阅

2、使用LiveData 的优点

1、确保UI 和 数据状态匹配

LiveData 遵循观察者模式。当生命周期状态发生改变时,LiveData 通知观察者对象。您可以合并代码来更新这些观察者对象中的UI,你的观察者可以在每次应用数据改变时更新UI,而不是每次应用数据改变时都更新UI

2、没有内存泄漏

观察者绑定到生命周期对象,并在其关联的生命周期被销毁后进行清理

3、没有因为停止活动而导致的崩溃

如果观察者的生命周期是不活动的,例如在后台栈中的活动,那么它不会接收任何liveData事件

4、不需要手动的生命周期处理

UI 组件只观察相关数据,不停止或继续观察。LiveData 会自动管理所有这些,因为 他在观察的同时会知道相关的生命周期状态变化

5、总是最新的数据

如果一个生命周期变为不活动的,它将在再次激活时接收最新的数据。例如,位于后台的活动在返回到前台后立即接收最新的数据。

6、适当的配置更改

如果某个活动或片段由于配置更改(如设备旋转)而重新创建,它将立即接收最新的可用数据。

7、共享资源

你可以使用单例模式来扩展LiveData对象来包装系统服务,这样它们就可以在你的应用程序中被共享。LiveData对象连接到系统服务一次,然后任何需要该资源的观察者都可以观看LiveData对象。有关更多信息,请参见Extend LiveData。

3、使用LiveData 对象

按照以下步骤处理LiveData对象:

1、创建一个LiveData实例来保存特定类型的数据。这通常在ViewModel类中完成。

2、创建一个定义onChanged()方法的观察者对象,该方法控制LiveData对象持有的数据更改时发生的情况。您通常在UI控制器中创建一个观察者对象,例如一个activity或fragment。

3、使用observe()方法将观察者对象附加到LiveData对象。方法获取一个LifecycleOwner对象。这订阅了LiveData对象的观察者对象,以便在发生更改时通知它。通常将观察者对象附加到UI控制器中,如 Activity或Fragment。

注意:您可以使用observeForever(observer)方法注册一个没有关联LifecycleOwner对象的观察者。在这种情况下,观察者被认为总是处于活动状态,因此总是被通知修改。您可以删除这些调用removeObserver(观察者)方法的观察者。

当您更新LiveData对象中存储的值时,只要附加的LifecycleOwner处于活动状态,它就会触发所有注册的观察者。

LiveData允许UI控制器观察者订阅更新。当LiveData对象持有的数据发生更改时,UI将自动更新。

1、创建LiveData 对象

LiveData是一个可以与任何数据(包括实现集合的对象,如List)一起使用的包装器。LiveData对象通常存储在ViewModel对象中,并通过getter方法进行访问,如下面的示例所示:

public class NameViewModel extends ViewModel{
    //create a LiveData with a String
    private MutableLiveData<String> currentName;
    
    public MutableLiveData<String> getCurrentName(){
        if(currentName == null){
            currentName = new MutableLiveData<String>();
        }
        return currentName;
    }
}

最初,并不设置LiveData对象中的数据。

注意:确保在ViewModel对象中存储更新UI的LiveData对象,而不是activity或fragment,原因如下:

以避免膨胀的活动和碎片。现在这些UI控制器负责显示数据而不是保存数据状态。

将LiveData实例与特定的活动或片段实例解耦,并允许LiveData对象在配置更改后仍然存在。

您可以在ViewModel指南中了解更多关于ViewModel类的好处和用法。

2、观察LiveData 数据

在大多数情况下,应用程序组件的onCreate()方法是开始观察LiveData对象的合适位置,原因如下:

以确保系统不会从活动或fragment的onResume()方法发出冗余调用。

以确保活动或片段具有数据,可以在活动开始时立即显示这些数据。只要应用程序组件处于启动状态,它就会从它所观察的LiveData对象接收最新的值。只有在设置了要观察的LiveData对象时才会发生这种情况。

通常,LiveData只在数据发生更改时才提交更新,并且只向活动的观察者提交更新。这种行为的一个例外是,当观察者从非活动状态更改为活动状态时,他们也会收到更新。而且,如果观察者第二次从非活动状态变为活动状态,那么它只会在上一次活动之后值发生变化时才会收到更新。

下面的示例代码演示了如何开始观察LiveData对象:

public class NameActivity extends AppCompatActivity{
    private NameViewModel model;
    
    @Override
    protected void onCreate(Bundle savedInstanceState){
        super.onCreate(saveInstanceState);
        
        //Get the ViewModel
        model = ViewModelProviders.of(this).get(NameViewModel.class);
        
        final Observer<String> nameObserver = new Observer<String>{
            @Override
            public void onChanged(@NUllable final String newName){
                nameTextView.setText(newName);
            }
        }
        model.getCurrentName().observe(this,nameObserver);
    }
}

使用作为参数传递的nameObserver调用了observe()之后,立即调用onChanged(),提供存储在mCurrentName中的最新值。如果LiveData对象没有在mCurrentName中设置值,则不会调用onChanged()。

3、更新LiveData对象

LiveData没有公开可用的方法来更新存储的数据。MutableLiveData类公开setValue(T)和postValue(T)方法,如果需要编辑存储在LiveData对象中的值,则必须使用这些方法。通常在ViewModel中使用MutableLiveData,然后ViewModel只向观察者公开不可变的LiveData对象。

建立观察者关系之后,可以更新LiveData对象的值,如下面的示例所示,当用户点击按钮时,将触发所有观察者:

button.setOnClickListener(new OnClickListener(){
	@Override
	public void onClick(View v){
		String anotherName = "John Doe";
		model.getCurrentName.setValue(anotherName);
	}
})

在示例中调用setValue(T)会导致观察者使用值John Doe调用它们的onChanged()方法。该示例显示一个按钮按下,但是可以调用setValue()或postValue()来更新mName,原因有很多,包括响应网络请求或完成数据库加载;在所有情况下,对setValue()或postValue()的调用都会触发观察者并更新UI。

注意:您必须调用setValue(T)方法来从主线程更新LiveData对象。如果代码在工作线程中执行,您可以使用postValue(T)方法来更新LiveData对象。

4、LiveData 和 Room 一起使用

Room 持久性库支持返回LiveData对象的可见查询。可观察查询是作为数据库访问对象(DAO)的一部分编写的。

当数据库更新时,Room生成更新LiveData对象所需的所有代码。生成的代码在需要时在后台线程上异步运行查询。此模式对于保持UI中显示的数据与数据库中存储的数据同步非常有用。您可以在Room persistent library指南中阅读关于Room和DAOs的更多信息。

与LiveData一起使用协同程序

LiveData包括对Kotlin协同程序的支持。有关更多信息,请参见使用带有Android体系结构组件的Kotlin协程。## 扩展LiveData

如果观察者的生命周期处于启动或恢复状态,LiveData认为观察者处于活动状态,下面的示例代码演示了如何扩展LiveData类:

public class StockLiveData extends LiveData<BigDecimal> {  
    private StockManager stockManager;   
    private SimplePriceListener listener = new SimplePriceListener() {   
        @Override
        public void onPriceChanged(BigDecimal price) {
            setValue(price);
        } 
    };   
    public StockLiveData(String symbol) {
        stockManager = new StockManager(symbol);
    }    
    
    @Override    
    protected void onActive() {  
        stockManager.requestPriceUpdates(listener);
    }   
    @Override
    protected void onInactive() { 
        stockManager.removeUpdates(listener);
    }
}

当LiveData对象有一个活动的观察者时,将调用onActive()方法。这意味着您需要开始观察来自此方法的股票价格更新。

当LiveData对象没有任何活动的观察者时,将调用onInactive()方法。因为没有观察者在听,所以没有理由保持与StockManager服务的连接。

setValue(T)方法更新LiveData实例的值,并将更改通知任何活动的观察者。

你可以使用StockLiveData类如下:

public class MyFragment extends Fragment {  
    @Override 
    public void onActivityCreated(Bundle savedInstanceState) 
    {   
        super.onActivityCreated(savedInstanceState);    
        LiveData<BigDecimal> myPriceListener = ...;   
        myPriceListener.observe(this, price -> {       
            // Update the UI.      
        });
    }
}

方法observe()将fragment(它是LifecycleOwner的一个实例)作为第一个参数传递。这样做表示这个观察者被绑定到与所有者相关联的生命周期对象,意思是:

如果生命周期对象没有处于活动状态,那么即使值发生变化也不会调用观察者。

在生命周期对象被销毁后,观察者被自动删除。

LiveData对象是生命周期感知的,这意味着您可以在多个活动、片段和服务之间共享它们。为了保持示例的简单性,可以将LiveData类实现为单例,如下所示:

public class StockLiveData extends LiveData<BigDecimal> { 
    private static StockLiveData sInstance; 
    private StockManager stockManager; 
    private SimplePriceListener listener = new SimplePriceListener() { 
        @Override  
        public void onPriceChanged(BigDecimal price) {    
            setValue(price);   
        }   
    };  
    
    @MainThread   
    public static StockLiveData get(String symbol) {   
        if (sInstance == null) {     
            sInstance = new StockLiveData(symbol);
        }        return sInstance; 
    }  
    private StockLiveData(String symbol) { 
        stockManager = new StockManager(symbol);
    } 
    
    @Override
    protected void onActive() {    
        stockManager.requestPriceUpdates(listener);  
    }  
    @Override  
    protected void onInactive() {     
        stockManager.removeUpdates(listener);   
    }
}

你可以在fragment 使用它:

public class MyFragment extends Fragment { 
    @Override 
    public void onActivityCreated(Bundle savedInstanceState) {   
        StockLiveData.get(symbol).observe(this, price -> { 
            // Update the UI.     
        }); 
    }
}

多个Fragment和actvity 可以观察MyPriceListener实例。LiveData仅在其中一个或多个服务可见且处于活动状态时才连接到系统服务。

5、变换LiveData

您可能希望在将LiveData对象发送给观察者之前对其存储的值进行更改,或者您可能需要根据另一个LiveData实例的值返回另一个LiveData实例。生命周期包提供转换类,该类包含支持这些场景的辅助方法。

[Transformations.map()](https://developer.android.google.cn/reference/androidx/lifecycle/Transformations.html#map(android.arch.lifecycle.LiveData, android.arch.core.util.Function))

将函数应用于存储在LiveData对象中的值,并将结果向下传播

LiveData<User> userLiveData = ...;
LiveData<String> userName = Transformations.map(userLiveData, user -> {    user.name + " " + user.lastName});

[Transformations.switchMap()](https://developer.android.google.cn/reference/androidx/lifecycle/Transformations.html#switchMap(android.arch.lifecycle.LiveData, android.arch.core.util.Function>))

与map()类似,将函数应用于LiveData对象中存储的值,并将结果解包并分发到下游。传递给switchMap()的函数必须返回LiveData对象,如下例所示:

private LiveData<User> getUser(String id) {
    
    ...;
}

LiveData<String> userId = ...;
LiveData<User> user = Transformations.switchMap(userId, id -> getUser(id) );

您可以使用转换方法来在观察者的生命周期中传递信息。除非观察者正在查看返回的LiveData对象,否则不会计算转换。因为转换是延迟计算的,所以与生命周期相关的行为是隐式传递的,不需要额外的显式调用或依赖关系。

如果您认为在ViewModel对象中需要一个生命周期对象,那么转换可能是更好的解决方案。例如,假设您有一个UI组件,它接受一个地址并返回该地址的邮政编码。你可以为这个组件实现朴素的ViewModel,如下面的示例代码所示:

class MyViewModel extends ViewModel{
    private final PostalCodeRepository repository;
    
    public MyViewModel(PostalCodeRepository respository){
        this.repository = respository;
    }
    
    private ListData<String> getPostalCode(String address){
        //don't do this
        return repository.getPostCode(address);
    }
    
}

然后,UI组件需要从先前的LiveData对象注销,并在每次调用getPostalCode()时注册到新实例。此外,如果重新创建了UI组件,它将触发对储存库. getpostcode()方法的另一个调用,而不是使用前一个调用的结果。

相反,您可以将邮政编码查找实现为地址输入的转换,如下面的示例所示:

class MyViewModel extends ViewModel{
	private final PostalCodeRepository repository;
    private final MutableLiveData<String> addressInput = new MutableLiveData();
    
    public final LiveData<String> postalCode = Transformations.switchMap(addressInput,(address) -> {
        return repository.getPostCode(address);
    })
 
    public MyViewModel(PostalCodeRepository repository){
        this.repository = repository;
    }
    
    private void setInput(String address){
        addressInput.setValue(address);
    }
    
        
}

在本例中,postalCode字段被定义为addressInput的转换。只要您的应用程序有一个与postalCode字段关联的活动观察者,每当addressInput发生更改时,就会重新计算和检索字段的值。

这种机制允许应用程序的低层创建按需延迟计算的LiveData对象。ViewModel对象可以很容易地获得对LiveData对象的引用,然后在其上定义转换规则。

4、创建新的转换

在你的应用程序中有许多不同的转换可能是有用的,但它们不是默认提供的。要实现自己的转换,可以使用MediatorLiveData类,它侦听其他LiveData对象并处理它们发出的事件。MediatorLiveData正确地将其状态传播到源LiveData对象。要了解关于此模式的更多信息,请参阅转换类的参考文档。

5、合并多个LiveData 源

MediatorLiveData是LiveData的一个子类,它允许您合并多个LiveData源。当任何原始LiveData源对象发生更改时,就会触发MediatorLiveData对象的观察者。

例如,如果您的UI中有一个可以从本地数据库或网络更新的LiveData对象,那么您可以将以下源添加到MediatorLiveData对象:

与数据库中存储的数据相关联的LiveData对象。

与从网络访问的数据相关联的LiveData对象。

您的活动只需要观察MediatorLiveData对象就可以接收来自两个源的更新。有关详细示例,请参见App架构指南的附录:暴露网络状态部分。

6、LiveData 源码分析

6.1、jar 包结构

androidx.lifecycle:lifecycle-livedata-core:

  • LiveData
  • MutableLiveData
  • Observer

androidx.lifecycle:lifecycle-livedata:

  • ComputableLiveData
  • MediatorLiveData
  • Transformations
6.1.1、具体类分析

LiveData:

LiveData是一个数据持有者类,可以在给定的生命周期内被观察到 包含了两种 注册方法 observe 方法以及 observeForever 方法

observe :

在生命周期内 进行监听 如果生命周期 为 STARTED 时一直进行监听,该监听在生命周期结束时自动取消监听,不需要remove 监听

    @MainThread
    public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer) {
        assertMainThread("observe");
        if (owner.getLifecycle().getCurrentState() == DESTROYED) {
            //如果 lifeRecycle destory 直接返回不做任何处理
            return;
        }
        //绑定了 LifeRecycle 组件
        LifecycleBoundObserver wrapper = new LifecycleBoundObserver(owner, observer);
        // 用 SafeIterableMap 来维护 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 实际上是一个 LifecycleObserver :

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

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

        @Override
        boolean shouldBeActive() {
            //生命为STARTED 时 监听liveData 对象的数据变化
            return mOwner.getLifecycle().getCurrentState().isAtLeast(STARTED);
        }

        @Override
        public void onStateChanged(LifecycleOwner source, Lifecycle.Event event) {
            //当生命周期为 DESTROYED 自动取消监听
            if (mOwner.getLifecycle().getCurrentState() == DESTROYED) {
                removeObserver(mObserver);
                return;
            }
            activeStateChanged(shouldBeActive());
        }

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

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

observeForever :在生命周期内 一直进行监听,该监听在生命周期结束时需要手动 removeObserver

    @MainThread
    public void observeForever(@NonNull Observer<? super T> observer) {
        assertMainThread("observeForever");
        //和 observe  不同在于 此处的观察者 为 AlwaysActiveObserver
        AlwaysActiveObserver wrapper = new AlwaysActiveObserver(observer);
        ObserverWrapper existing = mObservers.putIfAbsent(observer, wrapper);
        if (existing != null && existing instanceof LiveData.LifecycleBoundObserver) {
            throw new IllegalArgumentException("Cannot add the same observer"
                    + " with different lifecycles");
        }
        if (existing != null) {
            return;
        }
        wrapper.activeStateChanged(true);
    }

AlwaysActiveObserver:

    private class AlwaysActiveObserver extends ObserverWrapper {

        AlwaysActiveObserver(Observer<? super T> observer) {
            super(observer);
        }

        @Override
        boolean shouldBeActive() {
            return true; //一直返回的是true
        }
    }

当注册监听之后通过 setValue 进行触发(observe):

    @MainThread
    protected void setValue(T value) {
        assertMainThread("setValue");
        mVersion++;
        mData = value;
        //分发状态变化
        dispatchingValue(null);
    }

    @SuppressWarnings("WeakerAccess") /* synthetic access */
    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;
    }

    private void considerNotify(ObserverWrapper observer) {
        if (!observer.mActive) {
            return;
        }
       	//对应 LifecycleBoundObserver.shouldBeActive() 方法 
        if (!observer.shouldBeActive()) {
            observer.activeStateChanged(false);
            return;
        }
        // mVersion 在 setValue 方法中进行了 ++ (mVersion++;)
        if (observer.mLastVersion >= mVersion) {  
            return;
        }
        observer.mLastVersion = mVersion;
        //触发onChage 方法
        observer.mObserver.onChanged((T) mData);
    }

通过observeForever注册 Observer 方法内部和 observe 类似 observeForever 没有添加到LifeRecycle 中,故生命周期状态需要手动去 处理

MutableLiveData:

ComputableLiveData:

MediatorLiveData:

Transformations:

这几个类的解析以及综合流程我们下一章节 进行分析

7、LiveData 与 ViewModel 结合使用

7.1、 ViewModel 简介

ViewModel类被设计成以生命周期的方式存储和管理ui相关的数据。ViewModel类允许数据在配置更改(如屏幕旋转)后仍然存在。Android框架管理UI控制器的生命周期,比如acitivity和fragment。框架可能决定销毁或重新创建一个UI控制器,以响应某些用户操作或设备事件,这些操作或事件完全超出了您的控制。

如果系统破坏或重新创建一个UI控制器,那么您存储在其中的任何与UI相关的临时数据都将丢失。例如,您的应用程序可能在其某个活动中包含一个用户列表。当为配置更改重新创建活动时,新活动必须重新获取用户列表。对于简单数据,activity可以使用仅有()方法并恢复其包的数据在onCreate(),但这种方法只适用于少量的数据可以序列化反序列化,而不是潜在的大量数据的用户列表或位图。

另一个问题是UI控制器经常需要进行异步调用,这可能需要一些时间才能返回。UI控制器需要管理这些调用,并确保系统在销毁后对其进行清理,以避免潜在的内存泄漏。这种管理需要大量的维护,并且在为了配置更改而重新创建对象的情况下,这是对资源的浪费,因为对象可能不得不重新发出它已经发出的调用。

activikty和fragment等UI控制器主要用于显示UI数据、响应用户操作或处理操作系统通信(如权限请求)。要求UI控制器也负责从数据库或网络加载数据会使类膨胀。将过多的责任分配给UI控制器可能会导致单个类试图自己处理应用程序的所有工作,而不是将工作委托给其他类。以这种方式将过多的责任分配给UI控制器也会使测试变得更加困难。

将视图数据所有权从UI控制器逻辑中分离出来更简单、更有效。

7.2、ViewModel的生命周期

在这里插入图片描述

7.3、ViewModel 的用途

  • 在fragment 间共享数据

  • 用ViewModel 替换加载器

    • 在使用加载器的一种常见方法中,应用程序可能使用一个指针加载器来观察数据库的内容。当数据库中的一个值发生变化时,加载器会自动触发数据的重新加载,并更新用户界面:

在这里插入图片描述

  • 使用liveData

    ViewModel与Room和LiveData一起工作,以取代加载器。ViewModel确保数据在设备配置更改后仍然存在。当数据库发生更改时,Room会通知LiveData,而LiveData又会用修改后的数据更新您的UI。

在这里插入图片描述

  • 在ViewModel中使用协同程序

7.3、ViewModel 源码分析

7.3.1、ViewModelProviders:

ViewModelProviders :一个工具类,封装了 ViewModelStore 的一些方法 ,该类提供的方法创建了一个 ViewModelProvider 对象

   
	@NonNull
    @MainThread
    public static ViewModelProvider of(@NonNull FragmentActivity activity) {
        return of(activity, null);
    }
	
    @NonNull
    @MainThread
    public static ViewModelProvider of(@NonNull Fragment fragment) {
        return of(fragment, null);
    }

创建一个ViewModelProvider 对象

7.3.2、ViewModelProvider:

interface Factory:

  • create(@NonNull Class modelClass)

    用来创建一个ViewModel 对象

KeyedFactory implements Factory

  • Factory 的实现类 为生成的每一个 modelView 指定了一个key 值,生成的对象必须是 modelView 的子类

get(@NonNull Class modelClass) :

  • 获取viewModle 的核心方法,在activity 或者 fragemnt 中创建一个viewModel 或者返回一个存在的viewModel,该viewModel 作用于整个生命周期,所有viewModel 是通过一个 hashMap 进行维护

     @NonNull
        @MainThread
        public <T extends ViewModel> T get(@NonNull String key, @NonNull Class<T> modelClass) {
            ViewModel viewModel = mViewModelStore.get(key);
    		// 一个对象是本身类的一个对象
            if (modelClass.isInstance(viewModel)) {
                //如果该viewModel存在 返回 
                return (T) viewModel;  
            } else {
                if (viewModel != null) {
                    // TODO: log a warning.
                }
            }
            //如果没有指定Factory  使用默认的 AndroidViewModelFactory 来创建ViewModel
            if (mFactory instanceof KeyedFactory) {
                viewModel = ((KeyedFactory) (mFactory)).create(key, modelClass);
            } else {
                viewModel = (mFactory).create(modelClass);
            }
            mViewModelStore.put(key, viewModel);
            //noinspection unchecked
            return (T) viewModel;
        }
    

    vviewModelProvider 和 viewModelProviders 这两个类代码很简单功能也很简单 仅仅是创建了一个 通过了Factory 创建了viewModel 放到一个Map 中进行维护,有没有注意到 维护 viewModel 中的map 没有被创建,那么它是在哪被创建的呢? 在 lifecycle-viewmodel 包中还有一个接口呢 ViewModelStoreOwner

7.3.4、ViewModelStoreOwner :

该接口只有一个 getViewModelStore 方法,该接口在 ComponentActivity 中实现了,创建了一个viewModel 对象,该对象在该类的 构造方法中使用到了

ComponentActivity:

    @NonNull
    @Override
    public ViewModelStore getViewModelStore() {
        if (getApplication() == null) {
            throw new IllegalStateException("Your activity is not yet attached to the "
                    + "Application instance. You can't request ViewModel before onCreate call.");
        }
        if (mViewModelStore == null) {
            NonConfigurationInstances nc =
                    (NonConfigurationInstances) getLastNonConfigurationInstance();
            if (nc != null) {
                // Restore the ViewModelStore from NonConfigurationInstances
                mViewModelStore = nc.viewModelStore;
            }
            if (mViewModelStore == null) {
                //创建了一个ViewModelStore
                mViewModelStore = new ViewModelStore();
            }
        }
        return mViewModelStore;
    }
  getLifecycle().addObserver(new LifecycleEventObserver() {
            @Override
            public void onStateChanged(@NonNull LifecycleOwner source,
                    @NonNull Lifecycle.Event event) {
                if (event == Lifecycle.Event.ON_DESTROY) {
                    if (!isChangingConfigurations()) {
                        //清楚viewModelStore
                        getViewModelStore().clear();
                    }
                }
            }
        });

当 生命周期结束是 viewModelStore 中的 viewModel 被清空,这里有一个问题,viewModel对象放进 viewModelStore 中如何被监听数据的变化呢 ? 这里就需要jetPack 另外一个组件了 LiveData 也可以自定义实现 、结合RxJava 进行处理

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值