return currentSecond;
}
//开始定时器
public void startTiming(){
if(timer == null){
current = 0;
timer = new Timer();
TimerTask timerTask = new TimerTask() {
@Override
public void run() {
if(currentSecond!=null){
currentSecond.postValue(current++);
}
}
};
timer.schedule(timerTask,1000,1000);
}
}
//关闭定时器
public void stopTiming(){
timer.cancel();
}
}
1234567891011121314151617181920212223242526272829303132333435363738394041
当开始定时器的时候,也就是我们数据资源发生变化的时候,我们需要调用livedata.postvalue方法,通知页面我们数据源已经发生了改变。至于为什么不用livedata.setValue方法,等下我们会说到。
2.接着我们在Activity中创建ViewModel,并监听ViewModel里面currentSecond数据的变化。
public class LiveDataActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_live_data); iniComponent(); } private void iniComponent() { //通过ViewModelProvider得到ViewModel final LiveDataViewModel viewModel = new ViewModelProvider(this).get(LiveDataViewModel.class); //得到ViewModel中的LiveData final MutableLiveData liveData = (MutableLiveData) viewModel.getCurrentSecond(); //通过liveData.observer()观察ViewModel中数据的变化 liveData.observe(this, new Observer() { @Override public void onChanged(Integer integer) { //收到回调后更新UI界面 TextView tv = findViewById(R.id.tv_texts); tv.setText("小鑫啊"+integer); } }); //关闭定时器 findViewById(R.id.btnReset).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { //通过LiveData.setValue()/LiveData.postValue() //完成对ViewModel中数据的更新 liveData.setValue(0); //关闭定时器 viewModel.stopTiming(); } }); //计时开始 viewModel.startTiming(); } } 1234567891011121314151617181920212223242526272829303132333435363738394041424344 在页面中,通过LiveData.observe()方法对LivaData所包装的数据进行观察。当我们数据源发生变化了(也就是我们想修改LivaData所包装的数据时),就可以通过LiveData.postValue/LiveData.setValue()来完成,然后onChanged方法就会收到我们修改之后的数据,我们就可以对UI进行更改了. 需要注意的是:postValue()方法用在非UI线程中,而setValue()方法用在UI线程中,这就是为什么我们在开始定时器的时候,需要调用postVaule()发送数据了(因为定时器是运行在非UI线程的). ![image](https://img-blog.csdnimg.cn/img_convert/34233f4d394f2759d47ce065f8914d9b.png) **运行结果如下:** ![image](https://img-blog.csdnimg.cn/img_convert/a160420b3dca4e4c83d49796e04ac432.png) LivaData的基本使用就到这里,是不是很简单啊! 接下来,就让我们来探讨下LiveData的原理吧!!! []( )LiveData的原理 ====================================================================== 我们知道LiveData是通过观察者模式实现的。当数据发送改变的时候,会回调Observer的onChanged(),接下来就让我们深入Observer方法的源码一探究竟 []( )observe源码 ====================================================================
@MainThread 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); //判断当前wapper已经添加过,如果添加过就直接返回,否则返回null 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; } //没有添加过,则添加wrapper owner.getLifecycle().addObserver(wrapper); } 123456789101112131415161718192021 从源码可以看出,Observer()方法接收的第一个参数是一个LifecleOwner对象,我们传入的是this,因为this的祖父类实现了这个接口,也正是LifecleOwner对象,LiveData才会具体生命周期感知能力。 首先, 通过owner.getLifecycle().getCurrentState()获取当前页面的状态,如果当前页面被销毁了,就直接返回,也就是说LiveData会自动清除与页面的关联。 []( )LifecycleBoundObserver 源码 ====================================================================================
class LifecycleBoundObserver extends ObserverWrapper implements LifecycleEventObserver { @NonNull final LifecycleOwner mOwner; LifecycleBoundObserver(@NonNull LifecycleOwner owner, Observer<? super T> observer) { super(observer); mOwner = owner; } @Override boolean shouldBeActive() { return mOwner.getLifecycle().getCurrentState().isAtLeast(STARTED); } @Override public void onStateChanged(@NonNull LifecycleOwner source, @NonNull Lifecycle.Event event) { if (mOwner.getLifecycle().getCurrentState() == DESTROYED) { removeObserver(mObserver); return; } activeStateChanged(shouldBeActive()); } 1234567891011121314151617181920212223 当调用 LifecycleBoundObserver wrapper = new LifecycleBoundObserver(owner, observer),本质是通过 ObserverWrapper将observer包装起来,得以LiveData能对生命周期状态得以进行监听,是通过onStateChanged和shouldBeActive方法 1. shouldBeActive 这里调用LiftCycle的方法,表达如果当前生命周期的状态为onStart,onResume,onPause时 返回true,也就是说只有这三个状态可以接收数据更新。 2. onStateChanged 是LifecycleEventObserver接口的方法,当生命周期发送变化的时候会回调它,如果当前生命周期状态是destory,就会直接移除观察者,否则就会调用activeStateChanged(shouldBeActive());方法激活观察者. 方法中的最后一行代码将observer与Activity的生命周期关联在一起。因此,LivaData能够感知页面的生命周期。 []( )observer方法小结 ======================================================================= 1. 判断是否已经销毁,如果当前页面销毁,LiveData自动清除与页面的关联 2. 用LifecycleBoundObserver 对observer进行一个包装 3. 判断当前observer是否已经添加过,添加过就直接返回 4. 将observer方法与Activity的生命周期进行关联 []( )setValue方法 =====================================================================@MainThread protected void setValue(T value) { assertMainThread("setValue"); mVersion++; mData = value; dispatchingValue(null); } 1234567 setValue()中,首先 断言是主线程,这里的关键是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