记ViewModel和LiveData使用的一些坑与注意点

给出两个自己写的ViewModel:

public class MyViewModel extends AndroidViewModel implements Serializable {

    public static MyMutableLiveData<String> mAccount;

    public MyViewModel(@NonNull Application application) {
        super(application);
        mAccount = new MyMutableLiveData<>();
    }

    public void setAccount(String account){
        mAccount.setValue(account);
    }


    @Override
    protected void onCleared() {
        super.onCleared();
    }

    public static Observer<String>  observer = new MyObserver<String>();

    public static class MyObserver<T> implements Observer<T>,Serializable{

        @Override
        public void onChanged(T t) {
            Log.e("mvvmAccount","1234");
        }
    }

    public class MyMutableLiveData<T> extends MutableLiveData<T> implements Serializable{

    }


}

    vm.mAccount.observe(this,vm.observer);这样调用 

这样写可以在activity销毁的时候可以连带这个observer一起保留下来。


public class MyViewModel extends AndroidViewModel{

    public  MutableLiveData<String> mAccount;

    public MyViewModel(@NonNull Application application) {
        super(application);
        mAccount = new MutableLiveData<>();
    }

    public void setAccount(String account){
        mAccount.setValue(account);
    }


    @Override
    protected void onCleared() {
        super.onCleared();
    }

    
}

 只能这样调用:

vm.mAccount.observe(this, new Observer<String>() {
    @Override
    public void onChanged(String s) {
        
    }
});

先提出几个问题:

1.这两种observe的写法会造成什么影响:

第一种写法可以在activity销毁的时候可以连带这个observer一起保留下来

第二种其实每次都是new了新的observer

2.如果一个LiveData已经observe一次了,再observe一次会发生什么情况,为什么:

这个情况比较复杂分为:

a.在同一个activity(lifecycle)中使用同一个viewmodel和livedata来observe同一个observer  

b.在同一个activity(lifecycle)中使用同一个viewmodel和livedata来observe不同的observer

c.在不同的activity(lifecycle)中使用同一个viewmodel和livedata来observe同一个observer

d.在不同的activity(lifecycle)中使用同一个viewmodel和livedata来observe不同的observer

3.为什么在activity意外销毁重建比如横竖屏的时候重建后会立刻调用一次livedataObserver的onchange方法:

好了带着这些问题来看源码:

首先讲正常流程,在这个正常流程的源码中会有我自己理解的注释:

LiveData的setValue方法:

    @MainThread
    protected void setValue(T value) {
        assertMainThread("setValue");
        //这个mVersion特别重要大家记一下,在Livedata对象中维护这样一个int值
        //变量每次setValue都会加一,而且只会在这里变化,初始化在livedata的构造方法
        mVersion++;
        mData = value;
        //这个方法特别重要,这个会调用到observer的onchange方法
        dispatchingValue(null);
    }

    START_VERSION 初始值是-1
    public LiveData() {
        mData = NOT_SET;
        mVersion = START_VERSION;
    }

紧接着就是dispatchingVaule方法:

    void dispatchingValue(@Nullable ObserverWrapper initiator) {
        if (mDispatchingValue) {
            mDispatchInvalidated = true;
            return;
        }
        mDispatchingValue = true;
        do {
            mDispatchInvalidated = false;
            //dispatchingValue方法总共有两个地方调用一个是setValue一个activeStateChanged
            //一个是上面setValue方法参数是null,也就是说会走下面
            //另一种情况就是生命周期变化的时候,变为active的时候
            if (initiator != null) {
                considerNotify(initiator);
                initiator = null;
            } else {
            //下面会把livedata所有observe的observer都调一遍,重点是mObservers这个参数
            //所以有时候你setValue一次却调用了几个地方有可能就是observe了很多不同的observer
                for (Iterator<Map.Entry<Observer<? super T>, ObserverWrapper>> iterator =
                        mObservers.iteratorWithAdditions(); iterator.hasNext(); ) {
                    considerNotify(iterator.next().getValue());
                    if (mDispatchInvalidated) {
                        break;
                    }
                }
            }
        } while (mDispatchInvalidated);
        mDispatchingValue = false;
    }

继续往下调用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.
        //这里其实就是一个异常判断,如果lifecycle现在不是active状态那就给mActive
        //手动置成false
        if (!observer.shouldBeActive()) {
            observer.activeStateChanged(false);
            return;
        }
        //之前提到的mVersion,那observer.mLastVersion是什么,在什么时候赋值改变
        //这个判断能起到什么作用 下面会分析到 非常重要
        if (observer.mLastVersion >= mVersion) {
            return;
        }
        //除了赋初值只有这里会和mVersion同步一下
        observer.mLastVersion = mVersion;
        //noinspection unchecked
        observer.mObserver.onChanged((T) mData);
    }

上面就是从setValue到回调onchanged方法的全部流程

下面详细分析一下observer.mLastVersion:

observer是observerWrapper的子类LifecycleBoundObserver的实例,我们在livedata中用的都是LifecycleBoundObserver,这个比较重要稍后分析

  private abstract class ObserverWrapper {
        final Observer<? super T> mObserver;
        boolean mActive;
        //这里就是mLastVersion赋初值的地方,也是START_VERSION -1,那在哪里new 的 
        //observerWrapper的子类呢,是在observe方法里new LifecycleBoundObserver的时候
        int mLastVersion = START_VERSION;

        ObserverWrapper(Observer<? super T> observer) {
            mObserver = observer;
        }

        abstract boolean shouldBeActive();

        boolean isAttachedTo(LifecycleOwner owner) {
            return false;
        }

        void detachObserver() {
        }

        //这个方法最下面调用了dispatchingValue方法,这就是第二处调用dispatchingValue方法的地 
        //方,具体调用时机是在lifecycle变为active的时候,稍后分析
        void activeStateChanged(boolean newActive) {
            if (newActive == mActive) {
                return;
            }
            // immediately set active state, so we'd never dispatch anything to inactive
            // owner
            mActive = newActive;
            boolean wasInactive = LiveData.this.mActiveCount == 0;
            LiveData.this.mActiveCount += mActive ? 1 : -1;
            if (wasInactive && mActive) {
                onActive();
            }
            if (LiveData.this.mActiveCount == 0 && !mActive) {
                onInactive();
            }
            if (mActive) {
                dispatchingValue(this);
            }
        }
    }

接下来看LifecycleBoundObserver的使用:在livedata.observe的时候调用的

    @MainThread
    public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer) {
        assertMainThread("observe");
        if (owner.getLifecycle().getCurrentState() == DESTROYED) {
            // ignore
            return;
        }
     //这里非常重要 每次都会new一个新的ObserverWrapper这时后mLastVersion就赋予了初值-1 
        LifecycleBoundObserver wrapper = new LifecycleBoundObserver(owner, observer);
        //这里能解决上面2.c问题,如果一个Livedata已经observe了一个lifecycle还要想observ另一 
        //个lifecycle那就会抛异常crash
        ObserverWrapper existing = mObservers.putIfAbsent(observer, wrapper);
        if (existing != null && !existing.isAttachedTo(owner)) {
            throw new IllegalArgumentException("Cannot add the same observer"
                    + " with different lifecycles");
        }
        //这里能解决上面2.a,如果一个Livedata已经observe了一个lifecycle还要再次observe这个
        //lifecycle就会直接return。
        if (existing != null) {
            return;
        }
        owner.getLifecycle().addObserver(wrapper);
    }

//详细介绍mobserver
mobserver是啥:是一个map
private SafeIterableMap<Observer<? super T>, ObserverWrapper> mObservers =
            new SafeIterableMap<>();
    //这里就是上面调用的方法,他会先查看有没有这个(observer,wrapper)的entey,有直接返回没有才存到map中
    public V putIfAbsent(@NonNull K key, @NonNull V v) {
        Entry<K, V> entry = get(key);
        if (entry != null) {
            return entry.mValue;
        }
        put(key, v);
        return null;
    }

这里在注释中解决了2.a和2.c

下面解释mVersion判断的作用:

   if (observer.mLastVersion >= mVersion) {
            return;
        }

这个observer是ObserverWrapper,在leveData中其实就是LifecycleBoundObserver。

1.在livedata第一次observe的时候,这时lifecycle处于active状态会调用到activeStateChanged方法(在activiey或fragment中调用observe,lifecycle是active的会触发这个activeStateChanged方法)然后调用dispatchingValue(this);然后一步步调用到considerNotify方法这时被这个条件拦住了,因为这时候mversion是在livedata初始化的时候赋得初值为-1,而LifecycleBoundObserver也是新new的所以observer.mLastVersion值也是-1这时这里直接return了,所以我们第一次observe不会直接触发onchange方法

2.在setVaule的时候,mVersion加一在这里判断不成立会走到下面调用onchange方法

3.回答2.b问题:在同一个activity(lifecycle)中使用同一个viewmodel和livedata来observe不同的observer

因为是不同的oberver所以在livedata的observe方法中会new一个 LifecycleBoundObserver mLastVersion为-1,并且因为observer不同所以能走到最后一句addobserver,observe后lifecycle是active直接会调用到activeStateChanged方法,然后一步步执行到considerNotify方法,在判断observer.mLastVersion>=mVersion的时候observer.mLastVersion为-1,如果livedata已经调用过setValue方法那mVersion就大于-1这时会直接调用observer的onchange方法.

4.回答问题2.d和: own和observer全变了,所以执行liveData的observe方法会会new一个 LifecycleBoundObserver mLastVersion为-1,然后从observs的map中查找不到就addobserver之后和上面的流程一样。

回答问题3:先上一段代码

    @Override
    public void onStateChanged(LifecycleOwner source, Lifecycle.Event event) {
        //在activity异常销毁的时候就走这里就移除掉了observer
        if (mOwner.getLifecycle().getCurrentState() == DESTROYED) {
            removeObserver(mObserver);
            return;
        }
        activeStateChanged(shouldBeActive());
    }

在销毁的时候移除了observer,重建activity的时候就会重新添加,在observers中没有查找到,就addobserver,然后和上面的流程一样了

 

 

activeStateChanged方法如何在lifecycle变化时调用并且是如何处理的:

调用:

 

处理:

就是newActive和mActive的一个转换,如果之前mActive是false,newActive是true的时候:由非active变成active的时候,因为if (mActive) { dispatchingValue(this); }这个判断就会调用到dispatchingValue,如果由active变成非active就不会执行仅仅保存了状态.

  • 4
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,下面是一个简单的示例: 首先,我们需要在 `build.gradle` 文件中添加以下依赖项: ``` implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0' ``` 然后,我们需要创建一个包含计分逻辑的 `ScoreViewModel` 类,该类将托管我们的数据。该类需要继承自 `ViewModel`。 ```kotlin import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel class ScoreViewModel : ViewModel() { val teamAScore = MutableLiveData<Int>() val teamBScore = MutableLiveData<Int>() init { teamAScore.value = 0 teamBScore.value = 0 } fun addTeamAScore() { teamAScore.value = teamAScore.value?.plus(1) } fun addTeamBScore() { teamBScore.value = teamBScore.value?.plus(1) } } ``` 上述代码中,我们创建了一个 `ScoreViewModel` 类,该类包含两个 `MutableLiveData`,即 `teamAScore` 和 `teamBScore`。这两个变量存储着两个球队的得分,并且在我们的应用程序中可以随时更新。 我们还包含了两个方法 `addTeamAScore()` 和 `addTeamBScore()`,分别用于增加对应球队的得分。 接下来,我们需要创建一个 `MainActivity` 类,该类将托管我们的用户界面。 ```kotlin import androidx.appcompat.app.AppCompatActivity import android.os.Bundle import androidx.lifecycle.Observer import androidx.lifecycle.ViewModelProviders import kotlinx.android.synthetic.main.activity_main.* class MainActivity : AppCompatActivity() { private lateinit var scoreViewModel: ScoreViewModel override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) scoreViewModel = ViewModelProviders.of(this).get(ScoreViewModel::class.java) scoreViewModel.teamAScore.observe(this, Observer { score -> team_a_score.text = score.toString() }) scoreViewModel.teamBScore.observe(this, Observer { score -> team_b_score.text = score.toString() }) team_a_plus.setOnClickListener { scoreViewModel.addTeamAScore() } team_b_plus.setOnClickListener { scoreViewModel.addTeamBScore() } } } ``` 上述代码中,我们创建了一个 `MainActivity` 类,并在其中创建了一个 `ScoreViewModel` 的实例。 我们还使用了 `ViewModelProviders.of()` 方法来获取 `ScoreViewModel` 的实例,并使用 `observe()` 方法来观察 `teamAScore` 和 `teamBScore` 变量。每当这些变量更新时,我们将更新 UI 中对应的文本视图。 最后,我们为两个加分按钮设置了击侦听器,并使用 `addTeamAScore()` 和 `addTeamBScore()` 方法来增加对应球队的得分。 现在,当您运行应用程序时,您将看到两个球队的得分,并且您可以使用加分按钮来增加它们的分数。同时,这些更改将保存在 `ScoreViewModel` 中,并在配置更改后保持不变。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值