Android RecyclerView数据绑定
在本教程中,我们将在Android应用程序中讨论和实现RecyclerView using Data Binding。
Android RecyclerView数据绑定
为了了解Android DataBinding的基础知识,请访问本教程。
数据绑定大大减少了样板代码。
其中我们将学习如何使用具有ViewHolder模式的RecyclerView来实现DataBinding。
另外,我们还将了解数据绑定如何使通用化Adapter类变得容易。
最后,我们将演示如何直接在XML中传递适配器对象。
入门
在您应用的" build.gradle"中添加以下代码:
android{ ... dataBinding { enabled = true } ... }
添加以下依赖项。
implementation 'com.android.support:design:28.0.0'
项目结构
在以下应用程序中,我们将使用<data>将数据从XML加载到RecyclerView的适配器行中。
另外,我们将在布局行本身中设置onClickListener方法。
代码
下面给出了DataModel.java类的代码:
package com.theitroad.androidrecyclerviewdatabinding; public class DataModel { public String androidVersion, androidName; public DataModel(String androidName, String androidVersion) { this.androidName = androidName; this.androidVersion = androidVersion; } }
下面给出了" activity_main.xml"布局的代码:
<?xml version="1.0" encoding="utf-8"?> <layout xmlns:android="https://schemas.android.com/apk/res/android" xmlns:app="https://schemas.android.com/apk/res-auto"> <data> </data> <android.support.constraint.ConstraintLayout android:layout_width="match_parent" android:layout_height="match_parent"> <android.support.v7.widget.RecyclerView android:id="@+id/recyclerView" android:layout_width="match_parent" android:layout_height="match_parent" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent" app:layout_constraintTop_toTopOf="parent" </android.support.constraint.ConstraintLayout> </layout>
MainActivity.java
package com.theitroad.androidrecyclerviewdatabinding; import android.databinding.DataBindingUtil; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.support.v7.widget.LinearLayoutManager; import com.theitroad.androidrecyclerviewdatabinding.databinding.ActivityMainBinding; import java.util.ArrayList; import java.util.List; public class MainActivity extends AppCompatActivity { private ActivityMainBinding binding; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); binding = DataBindingUtil.setContentView(this, R.layout.activity_main); populateData(); } private void populateData() { List<DataModel> dataModelList = new ArrayList<>(); dataModelList.add(new DataModel("Android Oreo", "8.1")); dataModelList.add(new DataModel("Android Pie", "9.0")); dataModelList.add(new DataModel("Android Nougat", "7.0")); dataModelList.add(new DataModel("Android Marshmallow", "6.0")); MyRecyclerViewAdapter myRecyclerViewAdapter = new MyRecyclerViewAdapter(dataModelList, this); binding.setMyAdapter(myRecyclerViewAdapter); } }
RecyclerView的每一行的布局都在" item_row.xml"中定义。
<?xml version="1.0" encoding="utf-8"?> <layout xmlns:android="https://schemas.android.com/apk/res/android" xmlns:app="https://schemas.android.com/apk/res-auto"> <data> <variable name="model" type="com.theitroad.androidrecyclerviewdatabinding.DataModel" <variable name="itemClickListener" type="com.theitroad.androidrecyclerviewdatabinding.CustomClickListener" </data> <android.support.v7.widget.CardView android:layout_width="match_parent" android:layout_height="wrap_content" android:onClick="@{() -> itemClickListener.cardClicked(model)}" app:cardUseCompatPadding="true"> <LinearLayout android:layout_width="wrap_content" android:layout_margin="8dp" android:layout_height="wrap_content" android:orientation="vertical"> <TextView android:id="@+id/tvAndroidName" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@{model.androidName}" android:textAppearance="@style/TextAppearance.AppCompat.Headline" <TextView android:id="@+id/tvAndroidVersion" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@{model.androidVersion}" android:textAppearance="@style/TextAppearance.AppCompat.Subhead" </LinearLayout> </android.support.v7.widget.CardView> </layout>
在数据标签内,我们传递了两个变量-一个DataModel参考和一个CustomClickListener接口的参考,该接口的方法在CardView中被调用。
下面定义了CustomClickListener.java的代码:
package com.theitroad.androidrecyclerviewdatabinding; public interface CustomClickListener { void cardClicked(DataModel f); }
下面给出了MyRecyclerViewAdapter.java类的代码:
package com.theitroad.androidrecyclerviewdatabinding; import android.content.Context; import android.databinding.DataBindingUtil; import android.support.v7.widget.RecyclerView; import android.view.LayoutInflater; import android.view.ViewGroup; import android.widget.Toast; import java.util.List; import com.theitroad.androidrecyclerviewdatabinding.databinding.ItemRowBinding; public class MyRecyclerViewAdapter extends RecyclerView.Adapter<MyRecyclerViewAdapter.ViewHolder> implements CustomClickListener { private List<DataModel> dataModelList; private Context context; public MyRecyclerViewAdapter(List<DataModel> dataModelList, Context ctx) { this.dataModelList = dataModelList; context = ctx; } @Override public MyRecyclerViewAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { ItemRowBinding binding = DataBindingUtil.inflate( LayoutInflater.from(parent.getContext()), R.layout.item_row, parent, false); return new ViewHolder(binding); } @Override public void onBindViewHolder(ViewHolder holder, int position) { DataModel dataModel = dataModelList.get(position); holder.bind(dataModel); holder.itemRowBinding.setItemClickListener(this); } @Override public int getItemCount() { return dataModelList.size(); } public class ViewHolder extends RecyclerView.ViewHolder { public ItemRowBinding itemRowBinding; public ViewHolder(ItemRowBinding itemRowBinding) { super(itemRowBinding.getRoot()); this.itemRowBinding = itemRowBinding; } public void bind(Object obj) { itemRowBinding.setVariable(BR.model, obj); itemRowBinding.executePendingBindings(); } } public void cardClicked(DataModel f) { Toast.makeText(context, "You clicked " + f.androidName, Toast.LENGTH_LONG).show(); } }
为了将数据传递到XML副本,我们使用ʻitemRowBinding.setVariable(BR.model,obj);`将其绑定。
为了立即执行数据绑定,ʻexecutePendingBindings()`很重要。
否则会填充错误的视图。
setVariable()和setModel()之间的区别
在不知道数据类型的一般情况下使用setVariable()。
setModel()是自动生成的。
我们可以使用以下内容代替" holder.bind(dataModel);"。
holder.itemRowBinding.setModel(dataModel);
使用数据绑定在RecyclerView XML中传递适配器实例
由于数据绑定,我们可以通过在android:adapter属性内的XML中传递适配器实例,从而进一步减少MainActivity.java中的样板代码,如下所示:
activity_main.xml
<?xml version="1.0" encoding="utf-8"?> <layout xmlns:android="https://schemas.android.com/apk/res/android" xmlns:app="https://schemas.android.com/apk/res-auto"> <data> <variable name="myAdapter" type="com.theitroad.androidrecyclerviewdatabinding.MyRecyclerViewAdapter" </data> <android.support.constraint.ConstraintLayout android:layout_width="match_parent" android:layout_height="match_parent"> <android.support.v7.widget.RecyclerView android:id="@+id/recyclerView" android:layout_width="match_parent" android:layout_height="match_parent" android:adapter="@{myAdapter}" app:layoutManager="android.support.v7.widget.LinearLayoutManager" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent" app:layout_constraintTop_toTopOf="parent" </android.support.constraint.ConstraintLayout> </layout>
在MainActivity.java中,我们现在可以通过以下方式设置适配器:
MyRecyclerViewAdapter myRecyclerViewAdapter = new MyRecyclerViewAdapter(dataModelList, this); binding.setMyAdapter(myRecyclerViewAdapter);
因此,甚至不需要在Activity类中初始化RecyclerView。