接着上一篇继续(https://blog.youkuaiyun.com/zb987570437/article/details/103357030)
5.结合RecyclerView
Data Binding 除了在 Activity 中使用之外,还可以在 ListView 和 RecyclerView 中使用。
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recyclerview"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
</layout>
定义item的布局item_user_info:
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">
<data>
<import type="com.itzb.mvvmdemo.model.UserInfo" />
<variable
name="userInfo"
type="UserInfo" />
</data>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{userInfo.name}" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="30dp"
android:text="@{userInfo.pwd}" />
</LinearLayout>
</layout>
接下来定义RecyclerView的Adaper。
public class UserInfoAdapter extends RecyclerView.Adapter<UserInfoAdapter.UserInfoViewHolder> {
private List<UserInfo> datas;
public UserInfoAdapter(List<UserInfo> datas) {
this.datas = datas;
}
@NonNull
@Override
public UserInfoViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
ViewDataBinding binding = DataBindingUtil.inflate(LayoutInflater.from(parent.getContext()),
R.layout.item_user_info, parent, false);
;
return new UserInfoViewHolder(binding);
}
@Override
public void onBindViewHolder(@NonNull UserInfoViewHolder holder, int position) {
holder.binding.setUserInfo(datas.get(position));
}
@Override
public int getItemCount() {
return datas.size();
}
public class UserInfoViewHolder extends RecyclerView.ViewHolder {
ItemUserInfoBinding binding;
public UserInfoViewHolder(@NonNull ViewDataBinding binding) {
super(binding.getRoot());
this.binding = (ItemUserInfoBinding) binding;
}
}
}
与常规RecyclerView的Adaper使用方法不同的是,在上面代码注释1处我们没有将View传入UserInfoViewHolder中,而是将ItemUserInfoBinding传了进去。在UserInfoViewHolder中并没有通过findViewById 来找到相应的控件,而是提供了返回 ItemSwordsmanBinding 的getBinding 方法。最后将将相应 position 的 UserInfo 赋值给绑定的布局文件。最后在Activity中使用RecyclerView:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//1.先rebuild,2.书写代码绑定
ActivityMainBinding binding = DataBindingUtil.setContentView(this, R.layout.activity_main);
List<UserInfo> datas = new ArrayList<>();
for (int i = 0; i < 10; i++) {
datas.add(new UserInfo("123", "456"));
}
LinearLayoutManager layoutManager = new LinearLayoutManager(this);
UserInfoAdapter userInfoAdapter = new UserInfoAdapter(datas);
binding.recyclerview.setLayoutManager(layoutManager);
binding.recyclerview.setAdapter(userInfoAdapter);
}
}
MVVM与DataBinding
上面讲解的全是DataBinding的基础使用,到这里DataBinding也算是学会了,接下来结合MVVM简单模拟一个登录的实现。首先查看包结构
布局文件
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">
<!-- 定义该布局需要绑定的数据名称和类型-->
<data>
<variable
name="viewModel"
type="com.itzb.mvvmdemo.vm.LoginViewModel" />
</data>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<EditText
android:id="@+id/et_name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="请输入账号"
android:text="@={viewModel.userInfo.name}" />
<EditText
android:id="@+id/et_pwd"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="请输入密码"
android:text="@={viewModel.userInfo.pwd}" />
<Button
android:id="@+id/bt_login"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:onClick="@{viewModel.mLoginListener}"
android:text="登录" />
</LinearLayout>
</layout>
UserInfo作为javaBean比较简单,实际项目中Model包括真正获取数据的实现
public class UserInfo {
public ObservableField<String> name = new ObservableField<>();
public ObservableField<String> pwd = new ObservableField<>();
@Override
public String toString() {
return "UserInfo{" +
"name=" + name.get() +
", pwd=" + pwd.get() +
'}';
}
}
ViewModel则包含View和Model之间的逻辑代码
public class LoginViewModel {
Context context;
public UserInfo userInfo;
public LoginViewModel(ActivityMainBinding binding, Context context) {
//通过DataBinding工具将ViewModel和View绑定
binding.setViewModel(this);
this.context = context;
userInfo = new UserInfo();
}
public View.OnClickListener mLoginListener = new View.OnClickListener() {
@Override
public void onClick(View v) {
if ("123".equals(userInfo.name.get()) && "123".equals(userInfo.pwd.get())) {
Toast.makeText(context, "登录成功,userInfo: " + userInfo.toString(), Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(context, "登录失败", Toast.LENGTH_SHORT).show();
}
}
};
}
最后在Activity中完成绑定
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//1.先rebuild,2.书写代码绑定
ActivityMainBinding binding = DataBindingUtil.setContentView(this, R.layout.activity_main);
LoginViewModel loginViewModel = new LoginViewModel(binding, this);
}
}
利用DataBinding 的双向绑定,结合MVVM架构实现了简单的登录界面,运行效果图