Android-jetPack技术(Lifecycle、ViewModel、LiveData)
借用文档上面的话
Jetpack 是一套库、工具和指南,可帮助开发者更轻松地编写优质应用。这些组件可帮助您遵循最佳做法、让您摆脱编写样板代码的工作并简化复杂任务,以便您将精力集中放在所需的代码上。
Jetpack 包含与平台 API 解除捆绑的 androidx.* 软件包库。这意味着,它可以提供向后兼容性,且比 Android 平台的更新频率更高,以此确保您始终可以获取最新且最好的 Jetpack 组件版本。
Lifecycle 基本用发创建了一个类去实现了androidx这个包里面的LifecycleObserver接口;
看后面这个Observer,就知道是个观察者
@OnLifecycleEvent(Lifecycle.Event.ON_START)订阅我们需要回调的生命周期;
package com.example.lk;
import android.util.Log;
import androidx.lifecycle.Lifecycle;
import androidx.lifecycle.LifecycleObserver;
import androidx.lifecycle.OnLifecycleEvent;
public class MyLifeObserver implements LifecycleObserver {
@OnLifecycleEvent(Lifecycle.Event.ON_START)
private void onStartJett(){
Log.i("jett","onStartJett");
}
}
在Activity或者fragment中使用,进行绑定
//完成绑定
getLifecycle().addObserver(new MyLifeObserver());
ViewModel
基本使用
用ViewModel,我们可以无论在哪个界面或者什么任务中,只要去获取这个仓库,就可以改变视图。
使用ViewModel记得要导入依赖
//livedata+viewmodel
implementation 'androidx.lifecycle:lifecycle-extensions:2.0.0'
我们创建了一个类去继承了ViewModel 这个类
定义一个对象,相当于一个用来存放数据的仓库MutableLiveData,记得需要使用static静态的
模拟数据,并将数据添加到仓库中 liveData.setValue(data);
每次数据更新的时候,就调用 liveData.setValue(data);,前提是我们得是从这个仓库中取出来的值liveData.getValue()
setValue 这个方法一定要在主线程中调用!
postValue这个方法可以在子线程中调用,其实最后还是会调用到setValue这个方法;
具体为什么需要在主线程调用,以为postValue这个方法的调用,后续源码中去看。
package com.example.lk.viewmodel;
import androidx.lifecycle.LiveData;
import androidx.lifecycle.MutableLiveData;
import androidx.lifecycle.ViewModel;
import com.example.lk.R;
import com.example.lk.bean.Girl;
import java.util.ArrayList;
import java.util.List;
public class MyGirl extends ViewModel {
//定义一个对象,相当于一个用来存放数据的仓库
private static MutableLiveData<List> liveData;
//用于获取数据
public LiveData<List> getDataBean(){
if(liveData==null){
liveData=new MutableLiveData();
loadData();
}
return liveData;
}
private void loadData() {
List data;
data = new ArrayList();
data.add(new Girl(R.drawable.f1, "一星", "****"));
data.add(new Girl(R.drawable.f2, "一星", "****"));
data.add(new Girl(R.drawable.f3, "一星", "****"));
data.add(new Girl(R.drawable.f4, "一星", "****"));
//把这些数据存放到仓库里面
liveData.setValue(data);
}
//提供一个方法来改变数据
public void changeValue(int item,int i){
List value = liveData.getValue();
value.get(item).setLike(i+"");
liveData.setValue(value); //主线程调用
// liveData.postValue(value); //子线程中调用
}
}
我们去Activity中使用它
调用系统的API去初始化上面这个ViewModel; ViewModelProviders.of(this).get(MyGirl.class);
观察者订阅,用于数据更改时做更新myGirl.getDataBean().observe();
这样在其他地方一样的初始化这个ViewModel对象,都能去访问和更改这个数据了
package com.example.lk;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ListView;
import androidx.appcompat.app.AppCompatActivity;
import androidx.lifecycle.LiveData;
import androidx.lifecycle.Observer;
import androidx.lifecycle.ViewModelProviders;
import com.example.lk.adapter.GirlAdapter;
import com.example.lk.bean.Girl;
import com.example.lk.viewmodel.MyGirl;
import java.util.ArrayList;
import java.util.List;
public class MainActivity extends AppCompatActivity {
ListView listView;
List data;
MyGirl myGirl;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
listView=(ListView)findViewById(R.id.listview);
init();
listView.setAdapter(new GirlAdapter(MainActivity.this,data));
//完成绑定
getLifecycle().addObserver(new MyLifeObserver());
//调用系统API初始化这个对象
myGirl= ViewModelProviders.of(this).get(MyGirl.class);
myGirl.getDataBean().observe(this, new Observer<List>() {
@Override
public void onChanged(List girls) {
listView.setAdapter(new GirlAdapter(MainActivity.this,girls));
}
});
listView.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {
@Override
public boolean onItemLongClick(AdapterView parent, View view, int position, long id) {
myGirl.changeValue(position,1);
Intent intent=new Intent(MainActivity.this,SecActivity.class);
MainActivity.this.startActivity(intent);
return false;
}
});
}
//初始化默认数据
private void init() {
data = new ArrayList();
data.add(new Girl(R.drawable.f1, "一星", "****"));
data.add(new Girl(R.drawable.f2, "一星", "****"));
data.add(new Girl(R.drawable.f3, "一星", "****"));
data.add(new Girl(R.drawable.f4, "一星", "****"));
data.add(new Girl(R.drawable.f5, "一星", "****"));
}
}
例如我们新建一个类演示下
package com.example.lk;
import android.os.Bundle;
import android.widget.ListView;
import androidx.appcompat.app.AppCompatActivity;
import androidx.lifecycle.LiveData;
import androidx.lifecycle.ViewModelProviders;
import com.example.lk.bean.Girl;
import com.example.lk.viewmodel.MyGirl;
import java.util.List;
public class SecActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
MyGirl myGirl= ViewModelProviders.of(this).get(MyGirl.class);
//一定要在主线程中调用
myGirl.changeValue(0,666);
}
}
LiveData
基本使用
LiveData在使用的过程中是不需要导入任何包的
低版本好像是需要导包,具体导啥包,可以自行百度…
这个类就是上面图中的总线
自定义了一个泛型的BusMutableLiveData继承了泛型MutableLiveData,这一块的自定义类可以不做,这里是为了解决一个问题,所以我这里定义了这个类;
因为有很多用户会做消息订阅,所以我们创建了Map来存放订阅者;
定义了一个类去给用户做订阅的动作,也方便收集订阅者;
这个自定义的BusMutableLiveData类里面,我们为了解决去解决一个事件执行顺序的问题:当我们在第一个界面订阅和发布消息的时候, 跳转到第二个界面,第二个界面订阅的是同一个消息,进入第二个界面的时候,就会直接接收到第一个界面发布的消息;应该要先订阅后,发布者发布消息,才接受到消息
package com.example.lk;
import androidx.annotation.NonNull;
import androidx.lifecycle.LifecycleOwner;
import androidx.lifecycle.LiveData;
import androidx.lifecycle.MutableLiveData;
import androidx.lifecycle.Observer;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
public class LiveDataBus {
//存放订阅者 因为用到反射,所以我们这里没有去用泛型,而是用了Objsect
private Map<String, BusMutableLiveData> bus;
//单例
private static LiveDataBus liveDataBus=new LiveDataBus();
private LiveDataBus(){
bus=new HashMap();
}
public static LiveDataBus getInstance(){
return liveDataBus;
}
public synchronized BusMutableLiveData with(String key,Class type){
//如果是没有存过的
if(!bus.containsKey(key)){
//我们就去存
bus.put(key,new BusMutableLiveData());
}
return (BusMutableLiveData) bus.get(key);
}
public static class BusMutableLiveData extends MutableLiveData{
@Override
public void observe(@NonNull LifecycleOwner owner, @NonNull Observer observer) {
super.observe(owner, observer);
hook(observer);
}
private void hook(Observer observer) {
try{
//1.得到mLastVersion
Class liveDataClass=LiveData.class;
Field mObserversField = liveDataClass.getDeclaredField("mObservers");
mObserversField.setAccessible(true);
//获取到这个成员变量对应的对象
Object mObserversObject = mObserversField.get(this);
//得到map
Class mObserversObjectClass = mObserversObject.getClass();
//获取到mObservers对象的get方法
Method get=mObserversObjectClass.getDeclaredMethod("get",Object.class);
get.setAccessible(true);
//执行get方法
Object invokeEntry=get.invoke(mObserversObject,observer);
//取到map中的value
Object observerWraper=null;
if(invokeEntry!=null && invokeEntry instanceof Map.Entry){
observerWraper=((Map.Entry)invokeEntry).getValue();
}
if(observerWraper==null){
throw new NullPointerException("observerWraper is null");
}
//得到ObserverWrapper的类对象
Class superclass=observerWraper.getClass().getSuperclass();
Field mLastVersion = superclass.getDeclaredField("mLastVersion");
mLastVersion.setAccessible(true);
//2.得到mVersion
Field mVersion = liveDataClass.getDeclaredField("mVersion");
mVersion.setAccessible(true);
//3.把mVersion的值填入到mLastVersion中
Object mVersionValue=mVersion.get(this);
mLastVersion.set(observerWraper,mVersionValue);
}catch(Exception e){
e.printStackTrace();
}
}
}
}
我们来看看为什么是反射去把这个mVersion填入到mLastVersion中就可以解决
既然是想让订阅者获取不到消息,那我们去阻止这个消息的发出
我们反射更改if (observer.mLastVersion >= mVersion) {)这个地方
如果有这个需求的,把上面的hook()方法注释掉
public abstract class LiveData {
......
static final int START_VERSION = -1;
private int mVersion = START_VERSION;
......
private void considerNotify(ObserverWrapper observer) {
if (!observer.mActive) {
return;
}
//这里这个方法里面我们不去反射更改这个方法
if (!observer.shouldBeActive()) {
observer.activeStateChanged(false);
return;
}
//我们来反射这一块
if (observer.mLastVersion >= mVersion) {
return;
}
observer.mLastVersion = mVersion;
//noinspection unchecked
observer.mObserver.onChanged((T) mData);
}
}
再来看看这个我们的LiveDataBus的使用
package com.example.lk;
import androidx.appcompat.app.AppCompatActivity;
import androidx.lifecycle.Observer;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.Toast;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//消费者订阅消息
LiveDataBus.getInstance().with("huawei",Huawei.class)
.observe(this,new Observer() {
@Override
public void onChanged(Huawei huawei) {
if(huawei!=null){
Toast.makeText(MainActivity.this, huawei.getType(), Toast.LENGTH_SHORT).show();
}
}
});
}
public void sendMessage(View view) {
Huawei huawei=new Huawei("META-20");
//厂家发布消息
LiveDataBus.getInstance().with("huawei",Huawei.class).postValue(huawei);
}
public void startSecActivity(View view) {
Intent intent=new Intent(this,SecActivity.class);
startActivity(intent);
}
}
package com.example.lk;
import android.os.Bundle;
import android.view.View;
import android.widget.Toast;
import androidx.appcompat.app.AppCompatActivity;
import androidx.lifecycle.Observer;
public class SecActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//消费者订阅消息
LiveDataBus.getInstance().with("huawei",Huawei.class).observe(
this,
new Observer() {//观查者
@Override
public void onChanged(Huawei huawei) {
if(huawei!=null){
Toast.makeText(SecActivity.this, huawei.getType(), Toast.LENGTH_SHORT).show();
}
}
}
);
}
public void sendMessage(View view){
Huawei huawei=new Huawei("META-20");
//厂家发布消息
LiveDataBus.getInstance().with("huawei",Huawei.class).postValue(huawei);
}
}
浅析源码LiveData、ViewModel
我们这里看的是Android 26以后的源码;
ViewModelProviders.of(this)先获取了一下Application;
factory工厂第一次进来是个空,所以通过单例ViewModelProvider.AndroidViewModelFactory.getInstance(application);去创建一个AndroidViewModelFactory工厂,这里就是个全局唯一的工厂了,所以后面进来的时候,这个工厂都是不为空的;
最终返回了一个ViewModelProvider对象,所以of最终得到的是ViewModelProvider对象;
activity.getViewModelStore()方法是从NonConfigurationInstances对象去取一个缓存的ViewModel集合(viewModelStore),如果没有的话会new一个ViewModelStore出来,这个viewModelStore里面创建了一个HashMap键值对存放ViewModel对象;
public class ViewModelProviders {
......
@NonNull
@MainThread
public static ViewModelProvider of(@NonNull FragmentActivity activity) {
return of(activity, null);
}
......
@NonNull
@MainThread
public static ViewModelProvider of(@NonNull FragmentActivity activity,
@Nullable Factory factory) {
Application application = checkApplication(activity);
if (factory == null) {
factory = ViewModelProvider.AndroidViewModelFactory.getInstance(application);
}
return new ViewModelProvider(activity.getViewModelStore(), factory);
}
......
private static Application checkApplication(Activity activity) {
Application application = activity.getApplication();
if (application == null) {
throw new IllegalStateException("Your activity/fragment is not yet attached to "
+ "Application. You can't request ViewModel before onCreate call.");
}
return application;
}
}
ViewModelProviders.of(this).get(MyGirl.class)
上面of方法调用得到的是这个ViewModelProvider对象吧?
调用get方法的时候是传入了我们自己写的ViewModel这个子类,最终获取到这个自己写的ViewMode的实例;
1、这个get方法中获取了这个传入进来的类的全类名;
2、在调用了重载的get方法,传入了key,这个key是通过拼接DEFAULT_KEY和类名的方式作为key;
3、通过调用mViewModelStore.get(key)获取到这个ViewModel,这个ViewModelStore里面是用了个HashMap集合,键值对的方式储存的,也就是这类读取内存中是否存在这个ViewModel对象;
4、我们在MainActivity中第一次使用,所以我们这里从HashMap中读取肯定是拿不到这个ViewModel的;
5、所以这里 if (modelClass.isInstance(viewModel)) {}不会被直接return出去;
6、走入下面,会判断我们上面创建的工厂类型,通过不同的工厂类型去创建我们的ViewModel,下面内部类AndroidViewModelFactory 的create方法,通过反射创建了ViewModel的实例,然后添加到缓存的HashMap中;后续进来的类在HashMap中通过全类名能拿到ViewModel的是将不会在此创建,而是从缓存的HashMap中去进行拿取直接返回;
public class ViewModelProvider {
private static final String DEFAULT_KEY =
"androidx.lifecycle.ViewModelProvider.DefaultKey";
private final ViewModelStore mViewModelStore;
......
@NonNull
@MainThread
public T get(@NonNull Class 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);
}
......
@NonNull
@MainThread
public T get(@NonNull String key, @NonNull Class modelClass) {
ViewModel viewModel = mViewModelStore.get(key);
if (modelClass.isInstance(viewModel)) {
//noinspection unchecked
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);
}
mViewModelStore.put(key, viewModel);
//noinspection unchecked
return (T) viewModel;
}
......
public static class AndroidViewModelFactory extends ViewModelProvider.NewInstanceFactory {
private static AndroidViewModelFactory sInstance;
@NonNull
public static AndroidViewModelFactory getInstance(@NonNull Application application) {
if (sInstance == null) {
sInstance = new AndroidViewModelFactory(application);
}
return sInstance;
}
private Application mApplication;
public AndroidViewModelFactory(@NonNull Application application) {
mApplication = application;
}
@NonNull
@Override
public T create(@NonNull Class modelClass) {
if (AndroidViewModel.class.isAssignableFrom(modelClass)) {
//noinspection TryWithIdenticalCatches
try {
//反射的方法创建了ViewModel的实例
return modelClass.getConstructor(Application.class).newInstance(mApplication);
} catch (NoSuchMethodException e) {
throw new RuntimeException("Cannot create an instance of " + modelClass, e);
} catch (IllegalAccessException e) {
throw new RuntimeException("Cannot create an instance of " + modelClass, e);
} catch (InstantiationException e) {
throw new RuntimeException("Cannot create an instance of " + modelClass, e);
} catch (InvocationTargetException e) {
throw new RuntimeException("Cannot create an instance of " + modelClass, e);
}
}
return super.create(modelClass);
}
}
}
ViewModelStore这个类
里面就是一个HashMap,用来缓存ViewModel
package androidx.lifecycle;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Set;
public class ViewModelStore {
private final HashMap 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 keys() {
return new HashSet(mMap.keySet());
}
public final void clear() {
for (ViewModel vm : mMap.values()) {
vm.clear();
}
mMap.clear();
}
}
数据共享
这里需要分析的是Activity与fragment之间的数据共享、以及屏幕旋转后,数据还有保存这一块;
我们的Activity是继承了AppCompatActivity这个Activity;
这个AppCompatActivity继承了FragmentActivity这个Activity;
这个FragmentActivity继承了ComponentActivity这个Activity;
onRetainNonConfigurationInstance()在onSaveInstanceState()之后被调用
这个方法里面会把ViewModelStore保存下来;
还记得这个ViewModelStore 吗?
这个类里面就是用HashMap通过键值对的方式存储了ViewModel对象
最终将这个存储ViewModel对象的缓存类保存到这个NonConfigurationInstances 对象的成员变量中去;
NonConfigurationInstances 类因为是静态的final内部类 所以这个类会一直跟着程序的生命周期吧,所以这个里面的成员变量是会常驻内存的吧,这个是Android 26以后源码中做的保存数据;
这里就会造成这一块的内存没有做释放,这样就会有助于ui重绘也不会丢失数据,屏幕旋转就是在重绘UI;
public class ComponentActivity extends androidx.core.app.ComponentActivity implements
LifecycleOwner,
ViewModelStoreOwner,
SavedStateRegistryOwner,
OnBackPressedDispatcherOwner {
//因为是静态的final内部类 所以这个类会一直跟着程序的生命周期吧,也就是这个里面的成员变量是会常驻内存的吧
static final class NonConfigurationInstances {
Object custom;
//缓存了ViewMpdel的这个类吧
ViewModelStore viewModelStore;
}
......
@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) {
mViewModelStore = new ViewModelStore();
}
}
return mViewModelStore;
}
@Override
@Nullable
public final Object onRetainNonConfigurationInstance() {
Object custom = onRetainCustomNonConfigurationInstance();
ViewModelStore viewModelStore = mViewModelStore;
if (viewModelStore == null) {
// No one called getViewModelStore(), so see if there was an existing
// ViewModelStore from our last NonConfigurationInstance
NonConfigurationInstances nc =
(NonConfigurationInstances) getLastNonConfigurationInstance();
if (nc != null) {
viewModelStore = nc.viewModelStore;
}
}
if (viewModelStore == null && custom == null) {
return null;
}
//公用的
NonConfigurationInstances nci = new NonConfigurationInstances();
nci.custom = custom;
//最终将这个存储ViewModel对象的缓存类保存到这个NonConfigurationInstances 对象的成员变量中去
nci.viewModelStore = viewModelStore;
return nci;
}
......
}
LiveData订阅
接下来来看这一块
通过myGirl.getDataBean()获取到了LiveData对象;
然后调用了LiveData类里面的订阅方法observe
myGirl.getDataBean().observe(this, new Observer<List>() {
@Override
public void onChanged(List girls) {
listView.setAdapter(new GirlAdapter(MainActivity.this,girls));
}
});
来看看这个observe这个方法
1、判断了下是否在主线程;
2、判断了下是否已经是onDestroy状态了;
3、将Activity和观察者包装到LifecycleBoundObserver这个对象里面;
4、将这个对象以键值对 的方式存入到集合,键(观察者),值(包装好的LifecycleBoundObserver对象),最终返回了一个ObserverWrapper对象;
5、最后调用addObserver(ObserverWrapper)进行了观察者的注册;
这里通过键值对的集合将这个观察者存了起来;
public abstract class LiveData {
......
@MainThread
public void observe(@NonNull LifecycleOwner owner, @NonNull Observer observer) {
//判断是否在主线程
assertMainThread("observe");
//判断了下是否已经onDestroy了,也就是判断下了当前这个订阅的Activity是否已经被关闭了吧
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);
}
......
}
数据更改liveData.setValue(value);
还记得这个mVersion吗?
我们在上面hook反射的时候用到的了…
setValue这个方法的调用
1、主线程的判断;这里就是上面说的为什么要在主线程调用
2、mVersion版本号递增;
3、将需要修改的值赋值到了全局变量mData中;
4、调用分发的方法 dispatchingValue
插一句
上面我们说过postValue是可以在子线程中调用,并且最后还是会调用setValue()这个方法;
我们来看看postValue方法的调用,这个方法里面没有直接去判断主线程吧…
但是数据上的赋值是加了同步锁;
最后调用了 ArchTaskExecutor.getInstance().postToMainThread(mPostValueRunnable);传递进去了一个Runnable对象,这里面基本就是new了主线程的Handler,调用了post方法运行了这个Runnable;
在Runnable中调用了setValue这个方法,这就是我上面说到的postValue最终会调用setValue方法
分发dispatchingValue这个方法中
是调用了这个considerNotify方法去通知观察者的;
这里面做了些判断,注意下 if (observer.mLastVersion >= mVersion) {}这个判断,还记得我们当时hook反射的时候,更改的这两个值吗?
最终调用观察者的onChanged方法,给我们注册的观察者进行了回调
public abstract class LiveData {
static final int START_VERSION = -1;
private int mVersion = START_VERSION;
......
private final Runnable mPostValueRunnable = new Runnable() {
@Override
public void run() {
Object newValue;
synchronized (mDataLock) {
newValue = mPendingData;
mPendingData = NOT_SET;
}
//noinspection unchecked
setValue((T) newValue);
}
};
......
@MainThread
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 {
//所有的观察者都拿了出来
for (Iterator<Map.Entry<Observer, ObserverWrapper>> iterator =
mObservers.iteratorWithAdditions(); iterator.hasNext(); ) {
considerNotify(iterator.next().getValue());
if (mDispatchInvalidated) {
break;
}
}
}
} while (mDispatchInvalidated);
mDispatchingValue = false;
}
......
protected void postValue(T value) {
boolean postTask;
synchronized (mDataLock) {
postTask = mPendingData == NOT_SET;
mPendingData = value;
}
if (!postTask) {
return;
}
ArchTaskExecutor.getInstance().postToMainThread(mPostValueRunnable);
}
......
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;
//回调观察者的onChanged方法
observer.mObserver.onChanged((T) mData);
}
......
}
可以看看这个postToMainThread方法的调用
就是我上面说的new了一个主线程的Handler,最终调用了handler的post方法去运行Runnable;
Looper.getMainLooper() 看过Handler源码的就知道这是拿到程序唯一的主线程Looper对象,这个Looper对象是在ActivityThread中创建的吧
public class DefaultTaskExecutor extends TaskExecutor {
......
@Override
public void postToMainThread(Runnable runnable) {
if (mMainHandler == null) {
synchronized (mLock) {
if (mMainHandler == null) {
mMainHandler = new Handler(Looper.getMainLooper());
}
}
}
//noinspection ConstantConditions
mMainHandler.post(runnable);
}
......
}
总结
ViewModel也是通过获得LiveData去做订阅
创建ViewModel
1、在创建ViewModel实例之前,先创建了ViewModelProvider对象,在创建ViewModelProvider对象的时候,还会去创建一个用来存放ViewModel的HashMap的对象ViewModelStore;
2、然后通过ViewModelProvider.get方法去获取ViewModel实例或者创建实例,里面先从ViewModelStore中的HashMap中通过key去获取ViewModel,为了就是查找是否有对应key的ViewModel缓存对象,如果有就直接用,如果没有就通过反射的方式创建了一个ViewModel实例,并存到了ViewModelStore中的HashMap中;
在订阅的时候
在订阅的时候,ViewModel通过获取到LiveData然后调用订阅的方法将我们new出来的观察者进行了包装,然后添加Map集合中,如果相同的ViewModel对象,那么久会存放在同一个观察者集合中;
setValue更改值的时候
用户更改数据调用postValue和setValue的时候,最终都是调用的是setValue这个方法,调用分发值的方法,三层判断后,调用了观察者的onChanged方法,将值回调给了观察者的onChanged的方法,这样我们在注册的观察者中,复写的onChanged方法中就能获取到set的值;
数据共享和屏幕旋转
至于这个ViewModel,在Android26以后,UI的重绘,fragment之间传值,都是可以直接用到这个ViewModel去给界面赋值,因为在ComponentActivity中,会将这个ViewModel储存的ViewModelStore对象进行赋值到一个内部类NonConfigurationInstances的成员变量中中,而这个内部类是一个静态的不可更改的类,所以这个类的生命周期跟随这个跟着应用,这个里面的ViewModelStore对象也会一直存在,直到应用结束
作者:倾尽杯中酒
免责声明:
① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。
② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341