ViewModel如何将事件和数据传送到Activity中?
我们可以使用MutableLiveData<T>
。
1. 准备数据类型
新建类MutableDemoVM
public class MutableDemoVM {
public int countPoint = 0;
public ObservableField<String> title = new ObservableField<>("使用MutableLiveData");
public ObservableField<String> timeStr = new ObservableField<>();
public ObservableField<Integer> count = new ObservableField<>(0);
public MutableLiveData<Void> liveDataOnBack = new MutableLiveData<>();
public MutableLiveData<Integer> countLiveData = new MutableLiveData<>();
public void onClickBack(View view) {
liveDataOnBack.setValue(null);
}
public void onClickAdd(View view) {
countPoint++;
count.set(countPoint);
countLiveData.setValue(countPoint);
}
}
监听到点击事件后,执行一些操作,然后把数据发送出去。
发送事件需要调用setValue
方法或者postValue
方法。
它们之间一个显著区别在于,setValue
方法必须要在主线程中执行,postValue
方法可以在任意线程执行。postValue
方法会把数据切换到主线程去发送。
如果在子线程中调用setValue
,会报IllegalStateException:Cannot invoke setValue on a background thread
。 setValue
方法进行了assertMainThread
检查。
另一个区别是,setValue
方法是立即将数据传送给监听器(观察者)。postValue
方法会把数据依次发送。
如果在主线程中调用postValue
后又立即调用setValue
,那么监听器会先拿到setValue
的数据,然后拿到postValue
的数据。
连续多次调用postValue
来发送数据,如果主线程没有来得及执行发送任务,监听器会接收到最后一次发送的数据。
2. layout
准备layout文件。设置监听与各个感兴趣的属性。
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">
<data>
<variable
name="vm"
type="com.rustfisher.tutorial2020.databinding.data.MutableDemoVM" />
</data>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="50dp"
android:orientation="horizontal">
<ImageView
android:layout_width="50dp"
android:layout_height="50dp"
android:onClick="@{vm.onClickBack}"
android:padding="10dp"
android:src="@drawable/ic_arrow_back_black_24dp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:gravity="center_vertical"
android:text="@{vm.title}"
android:textColor="#000000"
android:textSize="18sp" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:text='@{"count: "+String.valueOf(vm.count)}'
android:textSize="16sp" />
<Button
android:layout_width="100dp"
android:layout_height="50dp"
android:layout_gravity="center_horizontal"
android:layout_marginTop="20dp"
android:onClick="@{vm::onClickAdd}"
android:text="+" />
</LinearLayout>
</LinearLayout>
</layout>
3. Activity设置
需要使用androidx.appcompat.app.AppCompatActivity
,它支持了LifeCycle。
public class MutableDemo1 extends AppCompatActivity {
private ActMutableDemo1Binding binding;
private MutableDemoVM mVM = new MutableDemoVM();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
binding = DataBindingUtil.setContentView(this, R.layout.act_mutable_demo1);
binding.setVm(mVM);
// 设置观察者
mVM.liveDataOnBack.observe(this, new Observer<Void>() {
@Override
public void onChanged(Void aVoid) {
onBackPressed();
}
});
mVM.countLiveData.observe(this, new Observer<Integer>() {
@Override
public void onChanged(Integer count) {
Toast.makeText(getApplicationContext(), "count: " + count, Toast.LENGTH_SHORT).show();
}
});
}
}
在activity中设置观察者。设置方法是observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer)
。
这个方法必须在主线程中执行。