Android RecyclerView数据绑定:高效实现列表UI的终极指南
在本教程中,我们将深入探讨并实现在Android应用程序中使用数据绑定(Data Binding)的RecyclerView。
Android RecyclerView数据绑定
要了解Android数据绑定的基础知识,请访问本教程。数据绑定可以显著减少样板代码。在这里,我们将学习如何在采用ViewHolder模式的RecyclerView中实现数据绑定。此外,我们还将了解数据绑定如何使Adapter类的通用化变得更加简单。最后,我们将演示如何直接在XML中传递适配器对象。
开始使用
在你的应用的build.gradle
文件中添加以下代码:
android{
...
dataBinding {
enabled = true
}
...
}
添加下面的依赖项:
implementation 'com.android.support:design:28.0.0'
项目结构
在下面的应用程序中,我们将使用从XML加载适配器行数据到RecyclerView中。同时,我们将在布局行中设置onClickListenr
方法。
代码
以下是DataModel.java
类的代码:
package com.Olivia.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="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<data>
</data>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.recyclerview.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" />
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>
MainActivity.java
代码:
package com.Olivia.androidrecyclerviewdatabinding;
import android.databinding.DataBindingUtil;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import androidx.recyclerview.widget.LinearLayoutManager;
import com.Olivia.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="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<data>
<variable
name="model"
type="com.Olivia.androidrecyclerviewdatabinding.DataModel" />
<variable
name="itemClickListener"
type="com.Olivia.androidrecyclerviewdatabinding.CustomClickListener" />
</data>
<androidx.cardview.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>
</androidx.cardview.widget.CardView>
</layout>
在<data>
标签内部,我们传递了两个变量:DataModel
的引用和CustomClickListener
接口的引用,该接口的方法在CardView
中被调用。CustomClickListener.java
的代码如下所示:
package com.Olivia.androidrecyclerviewdatabinding;
public interface CustomClickListener {
void cardClicked(DataModel f);
}
下面是MyRecyclerViewAdapter.java
类的代码。
package com.Olivia.androidrecyclerviewdatabinding;
import android.content.Context;
import android.databinding.DataBindingUtil;
import androidx.recyclerview.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.ViewGroup;
import android.widget.Toast;
import java.util.List;
import com.Olivia.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, "您点击了 " + 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中RecyclerView数据绑定》的第2部分(共2部分)。
由于数据绑定,我们可以通过在XML中使用android:adapter
属性将适配器实例传递到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.Olivia.androidrecyclerviewdatabinding.MyRecyclerViewAdapter" />
</data>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:adapter="@{myAdapter}"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>
现在我们可以在MainActivity.java
中通过以下方式设置适配器:
MyRecyclerViewAdapter myRecyclerViewAdapter = new MyRecyclerViewAdapter(dataModelList, this);
binding.setMyAdapter(myRecyclerViewAdapter);
因此,在Activity类中甚至无需初始化RecyclerView。下面是上述应用程序的输出结果:
这就结束了本教程。您可以从下面的链接下载项目。