如何在MVVM/retrofit 架构中使用DataBinding 在RecyclerView 的一行中设置数据?
How to set data in a row of RecyclerView using DataBinding in MVVM/retrofit Architecture?
我有问题,我正在尝试在简单的项目中实现数据绑定,我只使用一个对象制作了一个示例,它很简单并且有效,但现在我正在尝试对列表执行此操作,这更难,因为我现在正在处理适配器。
所以现在我的 xml 布局在布局标签内,并在 xml 中声明了一个变量,定义了我要集成的模型,我的 activity_main 也在布局标签内
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
>
<data>
<variable
name="contract"
type="com.example.cosysimulation.models.ContractModel" />
</data>
<TextView
android:id="@+id/courtier"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="22sp"
android:text="@{contract.courtier}"
android:layout_marginTop="8dp"
android:layout_marginLeft="12dp"
android:layout_toLeftOf="@+id/contratImage"
android:textColor="@color/colorPrimaryDark"></TextView>
</layout>
这是我的 activity :
public class MainActivity extends AppCompatActivity {
ContractsListViewModel contractsListViewModel;
@BindView(R.id.contractList)
RecyclerView contractList;
RecyclerView.Adapter adapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ActivityMainBinding main = DataBindingUtil.setContentView(this, R.layout.activity_main);
ButterKnife.bind(this);
contractList.setLayoutManager(new LinearLayoutManager(this));
contractsListViewModel = ViewModelProviders.of(this).get(ContractsListViewModel.class);
contractsListViewModel.call();
contractsListViewModel.contractList.observe(this,contractModels -> {
adapter = new ContractListAdapter(MainActivity.this, contractModels);
contractList.setAdapter(adapter);
});
}
}
这是我的适配器:
public class ContractListAdapter extends RecyclerView.Adapter<ContractListAdapter.ContractViewHolder> {
List<ContractModel> contracts;
Context context;
public ContractListAdapter(Context context, List<ContractModel> contracts){
this.context = context;
this.contracts = contracts;
}
@NonNull
@Override
public ContractViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.contrat, parent, false);
return new ContractViewHolder(view);
}
@Override
public void onBindViewHolder(@NonNull ContractViewHolder holder, int position) {
holder.bind(contracts.get(position));
}
@Override
public int getItemCount() {
return this.contracts.size();
}
public class ContractViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener{
@BindView(R.id.courtier)
TextView courtier;
@BindView(R.id.contratImage)
ImageView contractImage;
public ContractViewHolder(@NonNull View itemView){
super(itemView);
ButterKnife.bind(this, itemView);
}
public void bind(ContractModel contractModel){
courtier.setText(contractModel.getCourtier());
}
}
}
这是我的合同模型:
public class ContractModel {
@SerializedName("courtier")
private String courtier;
public ContractModel(String courtier) {
this.courtier = courtier;
}
public String getCourtier() {
return courtier;
}
public void setCourtier(String courtier) {
this.courtier = courtier;
}
}
任何帮助将不胜感激,我在 Youtube 上找到的教程大多只显示一个对象的绑定,这样更容易。
所以您主要要求将 DataBinding
库与 RecyclerView
适配器一起使用。
首先,我只是操纵你的主要 class 以适应 DataBinding
,方法是使用数据绑定膨胀你的 RecyclerView
,并省略使用 ButterKnife
库。
您可以使用 activity 的 DataBinding
对象将布局中的视图扩展到 java,并使用它们的 ID,此处 DataBinding
库从xml 通过删除下划线并将每个单词的第一个字母转换为大写(从第二个单词开始)。例如,您可以使用以下内容扩充您的 RecyclerView:main.contractList
其中 xml 中的 RecyclerView ID 为 contract_list
.
public class MainActivity extends AppCompatActivity {
ContractsListViewModel contractsListViewModel;
// @BindView(R.id.contractList)
// RecyclerView contractList;
RecyclerView.Adapter adapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ActivityMainBinding main = DataBindingUtil.setContentView(this, R.layout.activity_main);
// ButterKnife.bind(this);
main.contractList.setLayoutManager(new LinearLayoutManager(this)); // "contract_list" is the id of the RecyclerView in the layout, so data binding removes the "_" and capitalize 1st letter of each word after the first one
contractsListViewModel = ViewModelProviders.of(this).get(ContractsListViewModel.class);
contractsListViewModel.call();
contractsListViewModel.contractList.observe(this,contractModels -> {
adapter = new ContractListAdapter(MainActivity.this, contractModels);
main.contractList.setAdapter(adapter);
});
}
}
回到您的问题:无需更改您的列表项布局,因为您通过数据绑定完美地做到了这一点。
现在,对于适配器:
就像获取 activity 布局的绑定对象一样,还有一个与您的列表项布局相关联的绑定对象,您必须在适配器中构建它,您可以在 onCreateViewHolder()
方法。
这里命名为ContratBinding
,这里你的布局命名为"contract.xml",如果你的布局命名为list_item.xml,那么你的对象将是ListItemBinding
.
然后您将自定义 ViewHolder
构造函数以接受 ContratBinding
实例而不是 View
实例。并将 binding.getRoot()
发送到它的超级 class 而不是视图;因为 getRoot()
returns 在使用 DataBinding
.
时根视图本身
当您在列表项布局中定义了一个名为 contract
的 <variable>
时,您必须在适配器中使用 setContract()
方法来让 xml 布局知道这个变量是什么。当您将数据与 onBindViewHolder()
.
中的视图绑定时,您通常可以这样做
您的适配器将是
public class ContractListAdapter extends RecyclerView.Adapter<ContractListAdapter.ContractViewHolder> {
List<ContractModel> contracts;
Context context;
public ContractListAdapter(Context context, List<ContractModel> contracts){
this.context = context;
this.contracts = contracts;
}
@NonNull
@Override
public ContractViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
// View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.contrat, parent, false);
// return new ContractViewHolder(view);
ContratBinding binding = DataBindingUtil.inflate(LayoutInflater.from(parent.getContext()), R.layout.contrat, parent, false); // ContratBinding >> as your list item layout named "contrat"
return new ContractViewHolder(binding);
}
@Override
public void onBindViewHolder(@NonNull ContractViewHolder holder, int position) {
// holder.bind(contracts.get(position));
holder.binding.setContract(contracts.get(position)); // "Contract" is the variable "name" provided in your <layout><data> within the list item layout
}
@Override
public int getItemCount() {
return this.contracts.size();
}
public class ContractViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener{
// @BindView(R.id.courtier)
// TextView courtier;
// @BindView(R.id.contratImage)
// ImageView contractImage;
private ContratBinding binding;
// public ContractViewHolder(@NonNull View itemView){
// super(itemView);
// ButterKnife.bind(this, itemView);
// }
public ContractViewHolder(@NonNull ContratBinding binding) {
super(binding.getRoot());
this.binding = binding;
}
// public void bind(ContractModel contractModel){
// courtier.setText(contractModel.getCourtier());
// }
}
}
我打算注释掉您的 ButterKnife
和不再与 DataBinding
一起使用的代码,以查看差异
希望这对您有所帮助,欢迎随时评论以获取更多帮助。
我有问题,我正在尝试在简单的项目中实现数据绑定,我只使用一个对象制作了一个示例,它很简单并且有效,但现在我正在尝试对列表执行此操作,这更难,因为我现在正在处理适配器。
所以现在我的 xml 布局在布局标签内,并在 xml 中声明了一个变量,定义了我要集成的模型,我的 activity_main 也在布局标签内
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
>
<data>
<variable
name="contract"
type="com.example.cosysimulation.models.ContractModel" />
</data>
<TextView
android:id="@+id/courtier"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="22sp"
android:text="@{contract.courtier}"
android:layout_marginTop="8dp"
android:layout_marginLeft="12dp"
android:layout_toLeftOf="@+id/contratImage"
android:textColor="@color/colorPrimaryDark"></TextView>
</layout>
这是我的 activity :
public class MainActivity extends AppCompatActivity {
ContractsListViewModel contractsListViewModel;
@BindView(R.id.contractList)
RecyclerView contractList;
RecyclerView.Adapter adapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ActivityMainBinding main = DataBindingUtil.setContentView(this, R.layout.activity_main);
ButterKnife.bind(this);
contractList.setLayoutManager(new LinearLayoutManager(this));
contractsListViewModel = ViewModelProviders.of(this).get(ContractsListViewModel.class);
contractsListViewModel.call();
contractsListViewModel.contractList.observe(this,contractModels -> {
adapter = new ContractListAdapter(MainActivity.this, contractModels);
contractList.setAdapter(adapter);
});
}
}
这是我的适配器:
public class ContractListAdapter extends RecyclerView.Adapter<ContractListAdapter.ContractViewHolder> {
List<ContractModel> contracts;
Context context;
public ContractListAdapter(Context context, List<ContractModel> contracts){
this.context = context;
this.contracts = contracts;
}
@NonNull
@Override
public ContractViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.contrat, parent, false);
return new ContractViewHolder(view);
}
@Override
public void onBindViewHolder(@NonNull ContractViewHolder holder, int position) {
holder.bind(contracts.get(position));
}
@Override
public int getItemCount() {
return this.contracts.size();
}
public class ContractViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener{
@BindView(R.id.courtier)
TextView courtier;
@BindView(R.id.contratImage)
ImageView contractImage;
public ContractViewHolder(@NonNull View itemView){
super(itemView);
ButterKnife.bind(this, itemView);
}
public void bind(ContractModel contractModel){
courtier.setText(contractModel.getCourtier());
}
}
}
这是我的合同模型:
public class ContractModel {
@SerializedName("courtier")
private String courtier;
public ContractModel(String courtier) {
this.courtier = courtier;
}
public String getCourtier() {
return courtier;
}
public void setCourtier(String courtier) {
this.courtier = courtier;
}
}
任何帮助将不胜感激,我在 Youtube 上找到的教程大多只显示一个对象的绑定,这样更容易。
所以您主要要求将 DataBinding
库与 RecyclerView
适配器一起使用。
首先,我只是操纵你的主要 class 以适应 DataBinding
,方法是使用数据绑定膨胀你的 RecyclerView
,并省略使用 ButterKnife
库。
您可以使用 activity 的 DataBinding
对象将布局中的视图扩展到 java,并使用它们的 ID,此处 DataBinding
库从xml 通过删除下划线并将每个单词的第一个字母转换为大写(从第二个单词开始)。例如,您可以使用以下内容扩充您的 RecyclerView:main.contractList
其中 xml 中的 RecyclerView ID 为 contract_list
.
public class MainActivity extends AppCompatActivity {
ContractsListViewModel contractsListViewModel;
// @BindView(R.id.contractList)
// RecyclerView contractList;
RecyclerView.Adapter adapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ActivityMainBinding main = DataBindingUtil.setContentView(this, R.layout.activity_main);
// ButterKnife.bind(this);
main.contractList.setLayoutManager(new LinearLayoutManager(this)); // "contract_list" is the id of the RecyclerView in the layout, so data binding removes the "_" and capitalize 1st letter of each word after the first one
contractsListViewModel = ViewModelProviders.of(this).get(ContractsListViewModel.class);
contractsListViewModel.call();
contractsListViewModel.contractList.observe(this,contractModels -> {
adapter = new ContractListAdapter(MainActivity.this, contractModels);
main.contractList.setAdapter(adapter);
});
}
}
回到您的问题:无需更改您的列表项布局,因为您通过数据绑定完美地做到了这一点。
现在,对于适配器:
就像获取 activity 布局的绑定对象一样,还有一个与您的列表项布局相关联的绑定对象,您必须在适配器中构建它,您可以在 onCreateViewHolder()
方法。
这里命名为ContratBinding
,这里你的布局命名为"contract.xml",如果你的布局命名为list_item.xml,那么你的对象将是ListItemBinding
.
然后您将自定义 ViewHolder
构造函数以接受 ContratBinding
实例而不是 View
实例。并将 binding.getRoot()
发送到它的超级 class 而不是视图;因为 getRoot()
returns 在使用 DataBinding
.
当您在列表项布局中定义了一个名为 contract
的 <variable>
时,您必须在适配器中使用 setContract()
方法来让 xml 布局知道这个变量是什么。当您将数据与 onBindViewHolder()
.
您的适配器将是
public class ContractListAdapter extends RecyclerView.Adapter<ContractListAdapter.ContractViewHolder> {
List<ContractModel> contracts;
Context context;
public ContractListAdapter(Context context, List<ContractModel> contracts){
this.context = context;
this.contracts = contracts;
}
@NonNull
@Override
public ContractViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
// View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.contrat, parent, false);
// return new ContractViewHolder(view);
ContratBinding binding = DataBindingUtil.inflate(LayoutInflater.from(parent.getContext()), R.layout.contrat, parent, false); // ContratBinding >> as your list item layout named "contrat"
return new ContractViewHolder(binding);
}
@Override
public void onBindViewHolder(@NonNull ContractViewHolder holder, int position) {
// holder.bind(contracts.get(position));
holder.binding.setContract(contracts.get(position)); // "Contract" is the variable "name" provided in your <layout><data> within the list item layout
}
@Override
public int getItemCount() {
return this.contracts.size();
}
public class ContractViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener{
// @BindView(R.id.courtier)
// TextView courtier;
// @BindView(R.id.contratImage)
// ImageView contractImage;
private ContratBinding binding;
// public ContractViewHolder(@NonNull View itemView){
// super(itemView);
// ButterKnife.bind(this, itemView);
// }
public ContractViewHolder(@NonNull ContratBinding binding) {
super(binding.getRoot());
this.binding = binding;
}
// public void bind(ContractModel contractModel){
// courtier.setText(contractModel.getCourtier());
// }
}
}
我打算注释掉您的 ButterKnife
和不再与 DataBinding
一起使用的代码,以查看差异
希望这对您有所帮助,欢迎随时评论以获取更多帮助。