MVVM+LiveData的一个疑点

MVVM+LiveData的一个疑点

之前一直用的MVP开发,最近有新项目要开发,所以想要这套方案来开发,在网上也有很多相关文章。总结了一下,对MVVM+ LiveData的使用一般有两种写法。

  1. 在Activity或者fragment中
 viewModel.getXXXLiveData().observe(this, new Observer<XXX>() {
            @Override
            public void onChanged(@Nullable XXX xx) {
                if (xx!= null) {
                    //…
                   //UI更新,或者调用databinding更新ui
                }
            }
        });
在ViewModel获得数据后,直接调用XXXLiveData.setValue(XXX)

很显然第二种要代码要简洁很多,熟悉LiveData的都知道,当调用LiveData的setValue的时候,注册的observer会调用onChanged方法。第二种并没有注册observer,这中间有什么玄机呢。后面以google的android-architecture项目,分支是todo-mvvm-live为例剖析原因。

  1. 布局文件:部分代码
<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">

    <data>

        <import type="android.view.View"/>

        <variable
            name="viewmodel"
            type="com.example.android.architecture.blueprints.todoapp.addedittask.AddEditTaskViewModel"/>
    </data>
........
  1. fragment中,databinding设置viewmodel类对象,部分代码
        ..........
        final View root = inflater.inflate(R.layout.addtask_frag, container, false);
        if (mViewDataBinding == null) {
            mViewDataBinding = AddtaskFragBinding.bind(root);
        }

        mViewModel = AddEditTaskActivity.obtainViewModel(getActivity());

        mViewDataBinding.setViewmodel(mViewModel);
        mViewDataBinding.setLifecycleOwner(getActivity());
        ...........
  1. viewModel中获得数据,更新UI
public class AddEditTaskViewModel extends ViewModel implements TasksDataSource.GetTaskCallback {

    // Two-way databinding, exposing MutableLiveData
    public final MutableLiveData<String> title = new MutableLiveData<>();

    ......
    public AddEditTaskViewModel(TasksRepository tasksRepository) {
        mTasksRepository = tasksRepository;
    }

    public void start(String taskId) {
         ......
 
        mTasksRepository.getTask(taskId, this);
    }

    @Override
    public void onTaskLoaded(Task task) {
        title.setValue(task.getTitle());
        ......
    }

这是一个标准的使用mvvm+liveData的demo。

分析

  1. 从AddtaskFragBinding开始。找到生成的这个类,查看源代码。
    AddtaskFragBinding是一个抽象类,实现类是AddtaskFragBindingImpl
public abstract class AddtaskFragBinding extends ViewDataBinding {
  @NonNull
  public final EditText addTaskDescription;

  @NonNull
  public final EditText addTaskTitle;

  @NonNull
  public final ScrollChildSwipeRefreshLayout refreshLayout;

  @Bindable
  protected AddEditTaskViewModel mViewmodel;

  protected AddtaskFragBinding(DataBindingComponent _bindingComponent, View _root,
      int _localFieldCount, EditText addTaskDescription, EditText addTaskTitle,
      ScrollChildSwipeRefreshLayout refreshLayout) {
    super(_bindingComponent, _root, _localFieldCount);
    this.addTaskDescription = addTaskDescription;
    this.addTaskTitle = addTaskTitle;
    this.refreshLayout = refreshLayout;
  }

  public abstract void setViewmodel(@Nullable AddEditTaskViewModel viewmodel);

  @Nullable
  public AddEditTaskViewModel getViewmodel() {
    return mViewmodel;
  }
  ......

可见setViewmodel是在AddtaskFragBindingImpl中实现。

public class AddtaskFragBindingImpl extends AddtaskFragBinding  {
  ...
  public void setViewmodel(@Nullable com.example.android.architecture.blueprints.todoapp.addedittask.AddEditTaskViewModel Viewmodel) {
        this.mViewmodel = Viewmodel;
        synchronized(this) {
            mDirtyFlags |= 0x8L;
        }
        notifyPropertyChanged(BR.viewmodel);
        super.requestRebind();
    }
....

}

这里吐槽一个点,在setViewmodel方法中参数Viewmodel的命名没有遵循驼峰命名法,哈哈,也是个小瑕疵。
设置了viewmodel。绑定什么时候开始呢。记得在给databinding设置viewmodel的时候。mViewDataBinding.setLifecycleOwner(getActivity());我们跟下这个流程。这个方法在ViewDataBinding类中

  @MainThread
    public void setLifecycleOwner(@Nullable LifecycleOwner lifecycleOwner) {
        if (mLifecycleOwner == lifecycleOwner) {
            return;
        }
        if (mLifecycleOwner != null) {
            mLifecycleOwner.getLifecycle().removeObserver(mOnStartListener);
        }
        mLifecycleOwner = lifecycleOwner;
        if (lifecycleOwner != null) {
            if (mOnStartListener == null) {
                mOnStartListener = new OnStartListener();
            }
            lifecycleOwner.getLifecycle().addObserver(mOnStartListener);
        }
        for (WeakListener<?> weakListener : mLocalFieldObservers) {
            if (weakListener != null) {
                weakListener.setLifecycleOwner(lifecycleOwner);
            }
        }
    }

核心就是一句代码 lifecycleOwner.getLifecycle().addObserver(mOnStartListener);往lifecycle中添加一个观察者mOnStartListener,lifecycle的原理就不在细诉了,网上有很多讲解这个原理的资料。

    public class OnStartListener implements LifecycleObserver {
        private OnStartListener() {
        }

        @OnLifecycleEvent(Lifecycle.Event.ON_START)
        public void onStart() {
            executePendingBindings();
        }
    }

得知在start阶段调用executePendingBindings()->executeBindingsInternal->executeBindings。executeBindings的实现在AddtaskFragBindingImpl中

 @Override
    protected void executeBindings() {
        ......
        com.example.android.architecture.blueprints.todoapp.addedittask.AddEditTaskViewModel viewmodel = mViewmodel;
        androidx.lifecycle.MutableLiveData<java.lang.String> viewmodelTitle = null;
       ......
                    if (viewmodel != null) {
                        // read viewmodel.title
                        viewmodelTitle = viewmodel.title;
                    }
                    updateLiveDataRegistration(1, viewmodelTitle);


                    if (viewmodelTitle != null) {
                        // read viewmodel.title.getValue()
                        viewmodelTitleGetValue = viewmodelTitle.getValue();
                    }
            }
      ......
    }

这里以title为例,viewmodelTitle存了livedata类型的变量title,调用updateLiveDataRegistration->updateRegistration

  protected boolean updateLiveDataRegistration(int localFieldId, LiveData<?> observable) {
        mInLiveDataRegisterObserver = true;
        try {
            return updateRegistration(localFieldId, observable, CREATE_LIVE_DATA_LISTENER);
        } finally {
            mInLiveDataRegisterObserver = false;
        }
    }

  private boolean updateRegistration(int localFieldId, Object observable,
            CreateWeakListener listenerCreator) {
        if (observable == null) {
            return unregisterFrom(localFieldId);
        }
        WeakListener listener = mLocalFieldObservers[localFieldId];
        if (listener == null) {
            registerTo(localFieldId, observable, listenerCreator);
            return true;
        }
        if (listener.getTarget() == observable) {
            return false;//nothing to do, same object
        }
        unregisterFrom(localFieldId);
        registerTo(localFieldId, observable, listenerCreator);
        return true;
    }

参数observable就是title,但类型怎么变成了Object,为什么这么设计,这里暂且不提,文末在论述。因为首次进来listener 是null,那么调用registerTo()方法

  protected void registerTo(int localFieldId, Object observable,
            CreateWeakListener listenerCreator) {
        if (observable == null) {
            return;
        }
        WeakListener listener = mLocalFieldObservers[localFieldId];
        if (listener == null) {
            listener = listenerCreator.create(this, localFieldId);
            mLocalFieldObservers[localFieldId] = listener;
            if (mLifecycleOwner != null) {
                listener.setLifecycleOwner(mLifecycleOwner);
            }
        }
        listener.setTarget(observable);
    }

listenerCreator.create创建出来的具体对象是什么类型呢。从方法调用来看listenerCreator对象就是CREATE_LIVE_DATA_LISTENER,这个可以在updateLiveDataRegistration看到。

  private static final CreateWeakListener CREATE_LIVE_DATA_LISTENER = new CreateWeakListener() {
        @Override
        public WeakListener create(ViewDataBinding viewDataBinding, int localFieldId) {
            return new LiveDataListener(viewDataBinding, localFieldId).getListener();
        }
    };

那说明了listenerCreator.create()创建的就是LiveDataListener.getListener()返回的对象,还有一句关键代码 listener.setLifecycleOwner(mLifecycleOwner);listener其实是LiveDataListener构造函数中创建。

private static class LiveDataListener implements Observer,
            ObservableReference<LiveData<?>> {
        final WeakListener<LiveData<?>> mListener;
        LifecycleOwner mLifecycleOwner;

        public LiveDataListener(ViewDataBinding binder, int localFieldId) {
            mListener = new WeakListener(binder, localFieldId, this);
        }

        @Override
        public void setLifecycleOwner(LifecycleOwner lifecycleOwner) {
            LifecycleOwner owner = (LifecycleOwner) lifecycleOwner;
            LiveData<?> liveData = mListener.getTarget();
            if (liveData != null) {
                if (mLifecycleOwner != null) {
                    liveData.removeObserver(this);
                }
                if (lifecycleOwner != null) {
                    liveData.observe(owner, this);
                }
            }
            mLifecycleOwner = owner;
        }

        @Override
        public WeakListener<LiveData<?>> getListener() {
            return mListener;
        }

        @Override
        public void addListener(LiveData<?> target) {
            if (mLifecycleOwner != null) {
                target.observe(mLifecycleOwner, this);
            }
        }

        @Override
        public void removeListener(LiveData<?> target) {
            target.removeObserver(this);
        }

        @Override
        public void onChanged(@Nullable Object o) {
            ViewDataBinding binder = mListener.getBinder();
            binder.handleFieldChange(mListener.mLocalFieldId, mListener.getTarget(), 0);
        }
    }
  private static class WeakListener<T> extends WeakReference<ViewDataBinding> {
        private final ObservableReference<T> mObservable;
        protected final int mLocalFieldId;
        private T mTarget;

        public WeakListener(ViewDataBinding binder, int localFieldId,
                ObservableReference<T> observable) {
            super(binder, sReferenceQueue);
            mLocalFieldId = localFieldId;
            mObservable = observable;
        }

        public void setLifecycleOwner(LifecycleOwner lifecycleOwner) {
            mObservable.setLifecycleOwner(lifecycleOwner);
        }
      public void setTarget(T object) {
            unregister();
            mTarget = object;
            if (mTarget != null) {
                mObservable.addListener(mTarget);
            }
        }
    .....

可以看到WeakListener类中的mObservable其实就是LiveDataListener类,所以最终调用的也是LiveDataListener的setLifecycleOwner,在这个方法里可以看到 liveData.observe(owner, this);这个liveData是mListener.getTarget()返回的,此时应该是null。在registerTo方法的最后一行 listener.setTarget(observable);observable是前面传进来的title,在WeakListener的setTarget中

    public void setTarget(T object) {
            unregister();
            mTarget = object;
            if (mTarget != null) {
                mObservable.addListener(mTarget);
            }
        }

调用了 mObservable.addListener(mTarget);回到LiveDataListener的addListener

     @Override
        public void addListener(LiveData<?> target) {
            if (mLifecycleOwner != null) {
                target.observe(mLifecycleOwner, this);
            }
        }

target.observe(mLifecycleOwner, this);似曾相识,target就是liveData类型的title对象,这里就是方法一的写法。

总结

方法二在底层其实也是调用了LiveData.observer方法,经过这么多步骤,终于解释清楚了我们为啥不需要显示observer,原来底层都帮我们处理好了,简化了代码。之前遗留一个问题。updateRegistration方法中第二个参数类型是Object,而不是LiveData,因为observable还有可能是ObservableField或者ObservableXXX,WeakListener是将target泛型化的。所以需要Object。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值