2.1、第一个Activity
以大家都熟悉的登录操作为例:三个文件LoginActivty.java、LoginViewModel.java、activity_login.xml
2.1.1、关联ViewModel
在activity_login.xml中关联LoginViewModel。
<variable
type=“com.goldze.mvvmhabit.ui.login.LoginViewModel”
name=“viewModel”
/>
…
variable - type:类的全路径
variable - name:变量名
2.1.2、继承BaseActivity
LoginActivity继承BaseActivity
public class LoginActivity extends BaseActivity<ActivityLoginBinding, LoginViewModel> {
//ActivityLoginBinding类是databinding框架自定生成的,对activity_login.xml
@Override
public int initContentView(Bundle savedInstanceState) {
return R.layout.activity_login;
}
@Override
public int initVariableId() {
return BR.viewModel;
}
@Override
public LoginViewModel initViewModel() {
//View持有ViewModel的引用,如果没有特殊业务处理,这个方法可以不重写
return ViewModelProviders.of(this).get(LoginViewModel.class);
}
}
保存activity_login.xml后databinding会生成一个ActivityLoginBinding类。(如果没有生成,试着点击Build->Clean Project)
BaseActivity是一个抽象类,有两个泛型参数,一个是ViewDataBinding,另一个是BaseViewModel,上面的ActivityLoginBinding则是继承的ViewDataBinding作为第一个泛型约束,LoginViewModel继承BaseViewModel作为第二个泛型约束。
重写BaseActivity的二个抽象方法
initContentView() 返回界面layout的id
initVariableId() 返回变量的id,对应activity_login中name=“viewModel”,就像一个控件的id,可以使用R.id.xxx,这里的BR跟R文件一样,由系统生成,使用BR.xxx找到这个ViewModel的id。
选择性重写initViewModel()方法,返回ViewModel对象
@Override
public LoginViewModel initViewModel() {
//View持有ViewModel的引用,如果没有特殊业务处理,这个方法可以不重写
return ViewModelProviders.of(this).get(LoginViewModel.class);
}
注意: 不重写initViewModel(),默认会创建LoginActivity中第二个泛型约束的LoginViewModel,如果没有指定第二个泛型,则会创建BaseViewModel
2.1.3、继承BaseViewModel
LoginViewModel继承BaseViewModel
public class LoginViewModel extends BaseViewModel {
public LoginViewModel(@NonNull Application application) {
super(application);
}
…
}
BaseViewModel与BaseActivity通过LiveData来处理常用UI逻辑,即可在ViewModel中使用父类的showDialog()、startActivity()等方法。在这个LoginViewModel中就可以尽情的写你的逻辑了!
BaseFragment的使用和BaseActivity一样,详情参考Demo。
2.2、数据绑定
拥有databinding框架自带的双向绑定,也有扩展
2.2.1、传统绑定
绑定用户名:
在LoginViewModel中定义
//用户名的绑定
public ObservableField userName = new ObservableField<>("");
在用户名EditText标签中绑定
android:text="@={viewModel.userName}"
这样一来,输入框中输入了什么,userName.get()的内容就是什么,userName.set("")设置什么,输入框中就显示什么。 注意: @符号后面需要加=号才能达到双向绑定效果;userName需要是public的,不然viewModel无法找到它。
点击事件绑定:
在LoginViewModel中定义
//登录按钮的点击事件
public View.OnClickListener loginOnClick = new View.OnClickListener() {
@Override
public void onClick(View v) {
}
};
在登录按钮标签中绑定
android:onClick="@{viewModel.loginOnClick}"
这样一来,用户的点击事件直接被回调到ViewModel层了,更好的维护了业务逻辑
这就是强大的databinding框架双向绑定的特性,不用再给控件定义id,setText(),setOnClickListene