本文用到了:dataBinding、android架构组件
在使用RecyclerView时,点击item事件,我们通常会写一个OnItemClickListener接口,然后回调监听。在这里我们用安卓架构组件的LiveData试一下吧~
官方 todo-mvvm-live 示例里用了一个 SingleLiveEvent (继承 MutableLiveData):
/**
* A lifecycle-aware observable that sends only new updates after subscription, used for events like
* navigation and Snackbar messages.
*
* This avoids a common problem with events: on configuration change (like rotation) an update
* can be emitted if the observer is active. This LiveData only calls the observable if there's an
* explicit call to setValue() or call().
*
* Note that only one observer is going to be notified of changes.
*/
public class SingleLiveEvent<T> extends MutableLiveData<T> {
private static final String TAG = "SingleLiveEvent";
private final AtomicBoolean mPending = new AtomicBoolean(false);
@MainThread
public void observe(LifecycleOwner owner, final Observer observer) {
if (hasActiveObservers()) {
Log.w(TAG, "Multiple observers registered but only one will be notified of changes.");
}
// Observe the internal MutableLiveData
super.observe(owner, new Observer() {
@Override
public void onChanged(@Nullable T t) {
if (mPending.compareAndSet(true, false)) { // 如果 mPending = true, 则设置为 false
observer.onChanged(t);
}
}
});
}
@MainThread
public void setValue(@Nullable T t) {
// 当调用setValue() 方法时,mPending设为true,
mPending.set(true);
super.setValue(t);
}
/**
* Used for cases where T is Void, to make calls cleaner.
*/
@MainThread
public void call() {
setValue(null);
}
}
在ViewModel类:
// 实例化 SingleLiveEvent ,会调用SingleLiveEvent类中的observe()方法
public SingleLiveEvent mOpenTaskEvent = new SingleLiveEvent<>();
// 返回LiveData
public SingleLiveEvent getOpenTaskEvent(){
return mOpenTaskEvent;
}
在Fragment:
// 订阅点击事件
mViewModel.getOpenTaskEvent().observe(this, new Observer() {
@Override
public void onChanged(@Nullable String s) {
Log.i("onChanged", s);
}
});
item点击事件:
0:OnTaskItemListener接口
public interface OnTaskItemListener {
void onItemClick(ToDo entity);
}
① 在xml中绑定listener,设置onClick:
"listener"
type="test.carrie.todomvvmtest.ui.OnTaskItemListener"/>
"match_parent"
android:layout_height="48dp"
android:gravity="center_vertical"
android:orientation="horizontal"
android:onClick="@{()->listener.onItemClick(obj)}"
>
② 在Adapter中:
public class OnItemClickListener implements OnTaskItemListener {
@Override
public void onItemClick(ToDo entity) {
mainViewModel.getOpenTaskEvent().setValue(entity.title); // 调用了 setValue() 方法,[SingleLiveEvent:] mPending=true, observe()中的 super.observe...onChanged(T) 响应,由于mPending为true,设置 observer.onChanged(t); 目的是为了让Fragment中的观察者收到订阅结果。
}
整个响应顺序:
public SingleLiveEvent mOpenTaskEvent = new SingleLiveEvent<>();
SingleLiveEvent.observe
Adapter.onItemClick
SingleLiveEvent.setValue
SingleLiveEvent.super.onChanged
SingleLiveEvent.observer.onChanged(t);
Fragment.observe.onChanged
如果不用SingleLiveEvent
,直接用MutableLiveData
:
// ViewModel
public MutableLiveData mMutableOpenTaskEvent = new MutableLiveData<>();
public MutableLiveData getOpenTaskEventMutable(){
return mMutableOpenTaskEvent;
}
// Adapter
public void onItemClick(ToDo entity) {
mViewModel.getOpenTaskEventMutable().setValue(entity.title);
}
// Fragment
mViewModel.getOpenTaskEventMutable().observe(this, new Observer() {
@Override
public void onChanged(@Nullable String s) {
LogUtil.i("onChanged", s);
}
});