Android Jetpack组件推荐的使用项目架构
image上面架构组件的功能如下:
- Activity和Fragment负责产品与用户的交互
- ViewModel作为数据的存储和驱动
- Resposity负责调度数据的获取(Room储存本地序列化的数据,Retrofit获取远程数据的数据)
ViewModel+ LiveData
ViewModel的优点:
- 解决了运行中断和界面重建时的数据保存问题 (横竖屏切换,导致Activity销毁并重新创建时,ViewMode仍然可以保留之前读取到的数据不会因为Activity的销毁而丢失,这样我们无需额外再浪费资源去再次请求数据)
- 配合LiveData实时获取最新数据
- 实现Activity中Fragment之间的数据交互(数据共享)
- 数据和界面的分离,使数据驱动界面 (ViewModel类被设计为通过lifecycle感知的方式存储和管理UI相关数据)
ViewModel的生命周期:
- ViewModel对象的范围是在获取ViewModel时传递给ViewModelProvider的Lifecycle生命周期
- ViewModel在内存中直到Activity销毁或Fragment被移除
- 系统首次调用活动对象的onCreate()方法时,通常会请求ViewModel
- 系统可能会在整个活动的整个生命周期中多次调用onCreate(),例如当设备屏幕旋转时
- ViewModel从第一次请求ViewModel直到活动完成并销毁时存在
ViewMode在其生命周期的范围内会一直保存在内存中,所以横竖屏切换 当切换手机横竖屏后,Activity会destroy并重新onCreate来重构当前界面,生命周期再次重新触发onCreate,但是ViewMode 并没有重新执行获取数据的操作。
由于 ViewModel 生命周期可能长与 activity 生命周期,所以为了避免内存泄漏 Google 禁止在 ViewModel 中持有 Context 或 activity 或 view 的引用。
如果有些请求数据的情况必须用到Context,在继承ViewMode的时候,可以改为继承AndroidViewMode,这个类会返回一个带有Context的构造函数。
ViewMode执行onCleared操作,这个是ViewMode的一个回调,表明当前Activity要彻底关闭,ViewMode需要做一些回收清理的操作
imageLiveData
优点:
- 确保UI界面的数据状态
- 没有内存泄漏,不会因为Activity的不可见导致Crash
- 一个存放可被观察的数据持有类,但与一般的被观察者不同的是,它是有生命周期感知功能,解决了android开发者需要去手动处理生命周期的痛点。
- 共享资源
viewMode.getUserLiveData().observe(this, new Observer<String>() {
@Override
public void onChanged(String users) {
fragment2.setText("fragment2==\n" + users);
}
});
LiveData是一个observable数据持有类,LiveData是生命周期感知的,这意味着它跟随其他应用程序组件(如activities, fragments, or services)的生命周期。这种感知能力确保LiveData只更新处于活跃生命周期状态的应用程序组件
LiveData与一个Observer关联,如果观察者的生命周期处于STARTED或RESUMED状态,则表示观察者处于活动状态。LiveData只通知活跃的观察者做更新。注册到LiveData对象中的不活跃的观察者则得不到数据更新的通知。
注册一个observer并与实现了LifecycleOwner接口的对象配对。这种关系允许当相应的Lifecycle对象的状态改变为DESTROYED时,观察者被移除
利用ViewMode(配合LiveData实时获取最新数据)进行Fragment之间的数据交互
public class OneFragment extends BaseFragment {
@BindView(R2.id.fragment2)
TextView fragment2;
@Override
protected int initLayout() {
return R.layout.fragment_detail;
}
@Override
protected void initView(View view) {
//绑定ViewMode的selected的值,当有更新时通知DetailFragment
SharedViewModel viewMode = ViewModelProviders.of(getActivity()).get(SharedViewModel.class);
viewMode.getUserLiveData().observe(this, new Observer<String>() {
@Override
public void onChanged(String users) {
fragment2.setText("fragment2==\n" + users);
}
});
}
}
public class TwoFragment extends BaseFragment {
@BindView(R2.id.fragment1)
TextView fragment1;
SharedViewModel viewMode;
@Override
protected void initView(View view) {
//注意:这里ViewModelProviders.of(getActivity())这里的参数需要是Activity,而不能是Fragment,否则收不到监听
viewMode = ViewModelProviders.of(getActivity()).get(SharedViewModel.class);
fragment1.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//当点击某一个item的时候,更新viewmode中的selected的值
viewMode.select("fragment1点击后,更新viewmode中的值,fragment2 里面的数据同步更新");
}
});
}
@Override
protected void initData() {
viewMode.getUserLiveData().observe(this, new Observer<String>() {
@Override
public void onChanged(String users) {
Log.w("TAG", "====" + users);
}
});
}
@Override
protected int initLayout() {
return R.layout.fragment_master;
}
}
public class SharedViewModel extends AndroidViewModel {
//userLiveData保存的是被选中的item的状态或者数据
private MutableLiveData<String> userLiveData;
public MutableLiveData<String> getUserLiveData() {
if (userLiveData == null) {
Log.w("TAG", "SharedViewModel-getUserLiveData");
userLiveData = new MutableLiveData<>();
}
return userLiveData;
}
//主要通过masterFragment进行调用交互,用来更新selected中的值
public void select(String item) {
userLiveData.setValue(item);
}
public SharedViewModel(@NonNull Application application) {
super(application);
}
/**
* 这里可以执行一些资源释放、数据清理的操作
* ViewMode会执行onCleared操作,这个是ViewMode的一个回调,
* 表明当前Activity要彻底关闭,ViewMode需要做一些回收清理的操作,如下代码:
*/
@Override
protected void onCleared() {
super.onCleared();
}
}
上述代码的逻辑很简单,OneFragment与TwoFragment并不直接进行交互,而是各自与ViewMode进行交互,OneFragment用来更新维护ViewMode中的数据,TwoFragment可以收到来自ViewMode中数据更新的通知。这样便达到了两个frangment之间的数据通信。
LifeCycles原理
Lifecycles是生命周期管理组件 另一组件的生命周期状态(随着Activity和Fragment)的变化而执行动作,support 26 以上的兼容包中的AppCompatActivity与Fragment中默认已实现了LifeCycleOwner接口,保证了LiveData及ViewModel具备了生命周期感知与内存缓存的能力。
场景使用:在平时的开发过程中,我们难免有些逻辑的执行是和UI的生命周期相结合的,需要在特定的生命周期中执行相应的方法,我们平时做的可能就是在View中的每个周期调用Present中获取数据的方法,然后在调用View的回调接口更新UI,但现在使用Lifecycles可以使用注解和观察的模式自动调用Observe中定义好的方法。
//谁观察生命周期 就注册谁 两个角色定义好后,需要让他们之间建立联系
//获取Lifecycle
getLifecycle().addObserver(new LocationListener());
public class LocationListener implements LifecycleObserver {
private static final String TAG = "TAG";
@OnLifecycleEvent(Lifecycle.Event.ON_CREATE)
public void onActivityCreate(LifecycleOwner owner) {
Log.w(TAG, "onActivityCreate");
}
@OnLifecycleEvent(Lifecycle.Event.ON_DESTROY)
public void onActivityDestroy(LifecycleOwner owner) {
Log.w(TAG, "onActivityDestroy");
}
@OnLifecycleEvent(Lifecycle.Event.ON_PAUSE)
public void onActivityPause(LifecycleOwner owner) {
Log.w(TAG, "onActivityPause");
}
@OnLifecycleEvent(Lifecycle.Event.ON_RESUME)
public void onActivityResume(LifecycleOwner owner) {
Log.w(TAG, "onActivityResume");
}
@OnLifecycleEvent(Lifecycle.Event.ON_START)
public void onActivityStart(LifecycleOwner owner) {
Log.w(TAG, "onActivityStart");
}
@OnLifecycleEvent(Lifecycle.Event.ON_STOP)
public void onActivityStop(LifecycleOwner owner) {
Log.w(TAG, "onActivityStop");
}
}
Lifecycle 原理 如何感知 activity 或 fragment 生命周期
1、activity 和 fragment 已经实现了 LifecycleOwner
2、出现了一个LifecycleRegistry,是 Lifecycle 的一个实现类。通过markState方法在onSaveInstanceState把 Lifecycle 状态标记为Lifecycle.State.CREATED。
3、onCreate 方法里有个ReportFragment,
4、利用 fragment 的特性,绑定了一个 fragment 然后在其生命周期dispatch()方法中调用了LifecycleRegistry的handleLifecycleEvent,此方法便是通知观察者的地方。Lifecycle.Event,判断执行事件后下一个到达的状态,然后使用moveToState()中修改活动的生命周期
5、通知观察者addObserver 后,把observer维护到ObserverWithState然后装到 map 里。
然后通过handleLifecycleEvent方法最终遍历map 通知 observer。
伪代码
public class ComponentActivity extends androidx.core.app.ComponentActivity implements LifecycleOwner{
private final LifecycleRegistry mLifecycleRegistry = new LifecycleRegistry(this);
@CallSuper
@Override
protected void onSaveInstanceState(@NonNull Bundle outState) {
mLifecycleRegistry.markState(Lifecycle.State.CREATED);
super.onSaveInstanceState(outState);
}
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mSavedStateRegistryController.performRestore(savedInstanceState);
ReportFragment.injectIfNeededIn(this);
if (mContentLayoutId != 0) {
setContentView(mContentLayoutId);
}
}
public void addObserver(@NonNull LifecycleObserver observer) {
State initialState = mState == DESTROYED ? DESTROYED : INITIALIZED;
ObserverWithState statefulObserver = new ObserverWithState(observer, initialState);
ObserverWithState previous = mObserverMap.putIfAbsent(observer, statefulObserver);
}
ViewModel 原理
getLifecycle().addObserver(new LifecycleEventObserver() {
@Override
public void onStateChanged(@NonNull LifecycleOwner source,
@NonNull Lifecycle.Event event) {
if (event == Lifecycle.Event.ON_DESTROY) {
if (!isChangingConfigurations()) {
getViewModelStore().clear();
}
}
}
});
ViewModel 和 onSaveInstaceState方法区别在于:ViewModel只能保存因为配置更改导致重建的数据,但是它能保存大量和复杂的数据;onSaveInstaceState能保存配置更改导致重建和资源限制导致重建的数据,但是它只能保存少量简单的数据。ViewModel使用SavedStateHandle能够保存资源限制导致重建的数据。
根据传入的Activity获取、创建、添加并以键值对保存Fragment,从VIewStore的Map中或Factory的create()中获取ViewMode
1、获取ViewProvider:
2、获取ViewModelStore:由前面的源码可以知道创建ViewProvider时传入两个参数:ViewModelStore 和 Factory;显然从名字就可以看出他们的作用,Factory负责创建,ViewModelStore负责存储
ViewModelStore内部维护者一个Map集合保存者ViewModel对象的键值对
ViewModel的生命周期要比Activity长一点。因为在ComponentActivity 实现了的getViewModelStore ,ViewModelStore在Activity重建前后能保持同一个对象就是通过NonConfigurationInstances实现的。
ActivityThread 里面performLaunchActivity方法里面,启动Activity 调用了Activity的attach方法,在这个方法,将已有的NonConfigurationInstances赋值给了新的Activity对象。所以Activity 获取到的ViewMode是同一个,
这样NonConfigurationInstances能保证ViewModelStore在Activity重建前后是同一个对象,同时也知道为啥ViewModel的生命周期比Activity的生命周期要长一点
LiveData 原理,如何做到生命周期感知:
涉及到LifecycleOwner属于另一个架构组件 lifecycle,lifecycle原理上面已经讲述
伪代码
//LiveData数据可以再通过observe方法进行数据回调的返回,如上代码中的onChanged回调。
// 从Livedata添加观察者的方法 observe 开始:
viewMode.getUsers().observe(this, new Observer<String>() {
@Override
public void onChanged(String users) {
viewmode_text.setText("viewMode获取到的数据--" + users);
}
});
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);
}
第一个参数为LifecycleOwner用于提供当前的生命周期状态,DESTROYED的时候不做任何操作。
第二个为观察者observer,首先把observer包装成了LifecycleBoundObserver,然后把LifecycleBoundObserver维护到mObservers里
private SafeIterableMap<Observer<? super T>, ObserverWrapper> mObservers = new SafeIterableMap<>();
mObservers是一个LinkedList结构的容器 通过putIfAbsent方法判断,容器中此观察者是不是已经存在,如果存在且LifecycleOwner不同的话则抛异常,LifecycleOwner相同则 return 不重复添加。
LifecycleBoundObserver实现了LifecycleObserver,为lifecycle 的观察者,通过上文的 observe方法添加到了lifecycle观察中,
接下来主要看LifecycleBoundObserver
通过此类持有 Livedata 的观察者observer,当 生命周期发生变化时 会回调onStateChanged方法,然后 Livedata 的观察者在onStateChanged中执行相应的逻辑。
@Override
public void onStateChanged(@NonNull LifecycleOwner source,
@NonNull Lifecycle.Event event) {
if (mOwner.getLifecycle().getCurrentState() == DESTROYED) {
removeObserver(mObserver);
return;
}
activeStateChanged(shouldBeActive());
}
//接着执行activeStateChanged
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);
}
}
通过巧妙的设计实现了:
1、状态没有变化,什么也不做。
2、变为活(active)就是调用onActive(),非活(inactive)就调用onInactive().
3、另外,变为活的话就调用dispatchingValue方法,此方法为回调观察者的方法
事件的通知
LiveData通过 setValue 或 postValue 方法去改变持有的数据,并通知观察者,最终都是调用dispatchingValue()方法:
void dispatchingValue(@Nullable ObserverWrapper initiator) {
........................................
//遍历之前注册的观察者
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.mLastVersion >= mVersion) {
return;
}
observer.mLastVersion = mVersion;
//开始通知了
observer.mObserver.onChanged((T) mData);
}
网友评论