LiveData 与 ViewModel 简单原理分析

LiveData

官方传送门

LiveData 是一种可观察的数据存储器类。与常规的可观察类不同,LiveData 具有生命周期感知能力,意指它遵循其他应用组件(如 Activity、Fragment 或 Service)的生命周期。这种感知能力可确保 LiveData 仅更新处于活跃生命周期状态的应用组件观察者。

添加依赖:

 // LiveData
implementation "androidx.lifecycle:lifecycle-livedata:2.2.0"

1.注册

LiveData类方法

public abstract class LiveData<T> {
	//...以上省略...
	public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer)
	//...以下省略...
}

LifecycleOwner 继承树:
LifecycleOwner 继承树
Fragment和FragmentActivity都实现了LifecycleOwner 接口

2. 传值

LiveData类:

@Override
     protected void postValue(T value) {
        boolean postTask;
        synchronized (mDataLock) {
            postTask = mPendingData == NOT_SET;
            mPendingData = value;
        }
        if (!postTask) {
            return;
        }
        ArchTaskExecutor.getInstance().postToMainThread(mPostValueRunnable);
    }
    
	private final Runnable mPostValueRunnable = new Runnable() {
        @Override
        public void run() {
            Object newValue;
            synchronized (mDataLock) {
                newValue = mPendingData;
                mPendingData = NOT_SET;
            }
            //noinspection unchecked
            setValue((T) newValue);
        }
    };

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

两个方法的区别:
postValue方法会运行在主线程
setValue方法会运行在当前线程

简单而言,使用postValue方法,调用的mObserver.onChanged()方法会运行在主线程;而setValue方法,调用的mObserver.onChanged()方法则可能会运行在主线程也可能运行在非主线程是当前线程而定。
postValue方法切换线程后最终会调用setValue方法。

3. LiveData执行流程

		//第一步:实例化LiveData
        val liveData = MutableLiveData<ClipData.Item>()
	    //第二步:注册observer
        liveData.observe(this, Observer<ClipData.Item> {
			//执行回调
		 })
        //第三步:传值
        liveData.postValue(ClipData.Item("postValue"))
        //或者
	    //liveData.setValue(ClipData.Item("postValue"))

每一次调用postValue或者setValue时,都会回调ObServe.onChange()方法。

至此,一个简单的LiveDataDemo已经完成。

简单分析一下LiveData原理
1、 注册:

  private SafeIterableMap<Observer<? super T>, ObserverWrapper> mObservers =
          new SafeIterableMap<>();
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);
  }

使用SafeIterableMap实例mObservers 存储observer对象。

2、传值(postValue/setValue)
setValue方法为例(postValue方法最终会调setValue方法)

   protected void setValue(T value) {
        assertMainThread("setValue");
        mVersion++;
        mData = value;
        dispatchingValue(null);
    }
    
    void dispatchingValue(@Nullable ObserverWrapper initiator) {
        if (mDispatchingValue) {
            mDispatchInvalidated = true;
            return;
        }
        mDispatchingValue = true;
        do {
            mDispatchInvalidated = false;
            if (initiator != null) {
                considerNotify(initiator);
                initiator = null;
            } else {
            	//遍历observe
                for (Iterator<Map.Entry<Observer<? super T>, ObserverWrapper>> iterator =
                        mObservers.iteratorWithAdditions(); iterator.hasNext(); ) {
                    //回调observe.onChange方法
                    considerNotify(iterator.next().getValue());
                    if (mDispatchInvalidated) {
                        break;
                    }
                }
            }
        } while (mDispatchInvalidated);
        mDispatchingValue = false;
    }

调用setValue方法后,遍历mObservers,符合条件则回调observer.onChange方法。

LiveData + ViewModel

官方传送门

ViewModel 类旨在以注重生命周期的方式存储和管理界面相关的数据。ViewModel 类让数据可在发生屏幕旋转等配置更改后继续留存。

添加ViewModel依赖:

implementation "androidx.lifecycle:lifecycle-viewmodel:2.2.0"

1、创建ViewModel实现类

public class SingleViewModel extends ViewModel {
   private MutableLiveData<String> singleLiveData;
   public MutableLiveData<String> getSingleLiveData() {
       if (singleLiveData == null) {
           singleLiveData = new MutableLiveData<String>();
       }
       return singleLiveData;
   }
}

2、实例化ViewModel实例

//获取ViewModelProvider对象
public ViewModelProvider(@NonNull ViewModelStoreOwner owner) ;
//实例化ViewModel
public <T extends ViewModel> T get(@NonNull Class<T> modelClass);

3、为LiveData注册Observe

//Fragment中
var model = ViewModelProvider(requireActivity()).get(SingleViewModel::class.java)
//注册Observe
model.singleLiveData.observe(requireActivity(), Observer { 
	//回调
 })

4、传值

  model.singleLiveData.value = "click count ${count++}"

注意:

解析原理:
1、ViewModelStoreOwner
ViewModelStoreOwner的继承树:ViewModelStoreOwner的继承树

public interface ViewModelStoreOwner {
    /**
     * Returns owned {@link ViewModelStore}
     *
     * @return a {@code ViewModelStore}
     */
    @NonNull
    ViewModelStore getViewModelStore();
}

FragmentActivity和Fragment都实现了ViewModelStoreOwner接口,换言之,都可以通过FragmentActivity或Fragment获取ViewModelStore 实例

2、 ViewModelStore

public class ViewModelStore {
    private final HashMap<String, ViewModel> mMap = new HashMap<>();
//以下省略....
}

ViewModelStore通过HashMap存储ViewModel实例。

3、 ViewModelProvider


public class ViewModelProvider {

    private static final String DEFAULT_KEY =
            "androidx.lifecycle.ViewModelProvider.DefaultKey";
            
    //...以上省略...
	 public <T extends ViewModel> T get(@NonNull Class<T> modelClass) {
        String canonicalName = modelClass.getCanonicalName();
        if (canonicalName == null) {
            throw new IllegalArgumentException("Local and anonymous classes can not be ViewModels");
        }
        return get(DEFAULT_KEY + ":" + canonicalName, modelClass);
    }
    
	public <T extends ViewModel> T get(@NonNull String key, @NonNull Class<T> modelClass) {
		//根据key获取ViewModel
        ViewModel viewModel = mViewModelStore.get(key);
        //以下代码实例化ViewModel
        if (modelClass.isInstance(viewModel)) {
            if (mFactory instanceof OnRequeryFactory) {
                ((OnRequeryFactory) mFactory).onRequery(viewModel);
            }
            return (T) viewModel;
        } else {
            //noinspection StatementWithEmptyBody
            if (viewModel != null) {
                // TODO: log a warning.
            }
        }
        if (mFactory instanceof KeyedFactory) {
            viewModel = ((KeyedFactory) (mFactory)).create(key, modelClass);
        } else {
            viewModel = (mFactory).create(modelClass);
        }
        //存储ViewModel
        mViewModelStore.put(key, viewModel);
        return (T) viewModel;
    }
    //...以下省略...
}

ViewModelProvider中的mViewModelStore通过ViewModelStoreOwner.getViewModelStore()方法获得,而FragmentActivity和Fragment都是ViewModelStoreOwner的实现类,隐藏,ViewModelProvider中的mViewModelStore可以通过FragmentActivity和Fragment获得。

注意:如果需要ViewModel可以在Activity和Fragment中通信需要保证ViewModelStoreOwner是相同的。

单独的LiveData没办法在Activity和Fragment间通信,必须与ViewModel结合才行。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值