05 Jetpack-ViewModel & LiveData& LifeCycle

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需要做一些回收清理的操作

image
LiveData

优点:

  • 确保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);
    }

推荐阅读更多精彩内容