最近因为项目需要,采用了data bind 来封装了一下RecyclerView的适配器,抽象出了Adapter.
至于不了解data bind是什么可以点击这里。
我们仔细观察RecyclerAdapter可以发现主要是实现onCreateViewHolder(ViewGroup parent, int viewType)和onBindViewHolder(RecyclerView.ViewHolder holder, int position)这两个方法。
所以在我们的父类中我们将这两个方法抽出来。onCreateViewHolders是创建我们的ViewHolder所以这里我们只需拿到布局的引用即可
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
ViewDataBinding binding = DataBindingUtil.inflate(
LayoutInflater.from(parent.getContext()),
getItemLayoutId(viewType),
parent,
false);
final RecyclerViewHolder holder = new RecyclerViewHolder(binding.getRoot());
holder.setBinding(binding);
if( null != myItemClickListener){
holder.itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
myItemClickListener.onItemClick(holder.itemView,holder.getLayoutPosition());
}
});
}
if( null != myItemLongClickListener){
holder.itemView.setOnLongClickListener(new View.OnLongClickListener() {
@Override
public boolean onLongClick(View v) {
myItemLongClickListener.onItemLongClick(holder.itemView,holder.getLayoutPosition());
return true;
}
});
}
return holder;
}
onBindViewHolder()方法则主要是我们具体的操作。
@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
RecyclerViewHolder recyclerViewHolder = (RecyclerViewHolder) holder;
switch (mMode){
case TYPE_NORMAL:
bindData(recyclerViewHolder,mData.get(position));
break;
case TYPE_CUSTOM:
bindData(recyclerViewHolder,mData.get(position));
bindCustomData(recyclerViewHolder,position,mData.get(position));
break;
}
}
在父类中其实并不用管这些,子类只需继承并实现以下几个方法
/**
* 布局引用
* @param viewType
* @return
*/
abstract public int getItemLayoutId(int viewType);
/**
* data bind Variable 引用
* @return
*/
abstract public int getVariableId();
/**
* 自定义操作
* @param holder
* @param position
* @param item
*/
abstract public void bindCustomData(RecyclerViewHolder holder,int position,T item);
/**
* 加载模式
* @return
*/
abstract public int getStartMode();
getItemLayoutId()这个方法子类实现并返回你的布局文件引用。
getVariableId()这个是返回你布局中使用data binding所命名的变量引用。
bindCustomData()在这个方法中,如果你的布局复杂,可以实现自己具体的事件。
getStartMode()这个方法返回的是你所选择加载的模式,如果你需要使用bindCustomData()这个方法,你不能返回0.
在这里我们还实现了统一的ViewHolder
public class RecyclerViewHolder extends RecyclerView.ViewHolder {
private ViewDataBinding binding;
public RecyclerViewHolder(View itemView) {
super(itemView);
}
public ViewDataBinding getBinding() {
return binding;
}
public void setBinding(ViewDataBinding binding) {
this.binding = binding;
}
}
RecyclerViewHolder中使用了data binding框架。具体使用可以查看链接。
具体例子:
public class UserAdapter extends RecyclerBaseAdapter<User> {
public UserAdapter(List<User> mData, Context mContext) {
super(mData, mContext);
}
@Override
public int getItemLayoutId(int viewType) {
return R.layout.main_item;
}
@Override
public int getVariableId() {
return BR.users;
}
@Override
public void bindCustomData(RecyclerViewHolder holder, int position, User item) {
}
@Override
public int getStartMode() {
return 0;
}
}
可以看到我们继承了RecyclerBaseAdapter实现了一个UserAdapter在这个方法中实现了上面所述的4个方法。
我们的User也很简单:
public class User {
private String name;
private String avatar;
private String age;
public User(){
}
public User(String name, String avatar, String age) {
this.name = name;
this.avatar = avatar;
this.age = age;
}
public String getAvatar() {
return avatar;
}
public void setAvatar(String avatar) {
this.avatar = avatar;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAge() {
return age;
}
public void setAge(String age) {
this.age = age;
}
}
这有头像,名字,年龄
布局文件 main_item.xml
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<data>
<variable
name="users"
type="com.red.allrecyclerdemo.models.User"/>
</data>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="10dp"
android:orientation="horizontal">
<ImageView
android:layout_width="45dp"
android:layout_height="45dp"
android:scaleType="centerCrop"
app:error="@{@drawable/default_image}"
app:imageUrl="@{users.avatar}"/>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginLeft="5dp"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="5dp"
android:text="@{users.name}" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{users.age}"/>
</LinearLayout>
</LinearLayout>
</LinearLayout>
</layout>
该布局文件显示我们的头像,姓名,年龄而已,做为一个例子也是够了。
然后查看我们的MainActivity.java
public class MainActivity extends AppCompatActivity {
private UserAdapter mAdapter;
private List<User> mUsers;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ActivityMainBinding binding = DataBindingUtil.setContentView(this, R.layout.activity_main);
mUsers = new ArrayList<User>();
setData();
mAdapter = new UserAdapter(mUsers,MainActivity.this);
//设置布局管理器
binding.recyclerView.setLayoutManager(new LinearLayoutManager(this));
binding.recyclerView.setAdapter(mAdapter);
}
private void setData(){
for(int i = 0; i < 10; i++){
User user = new User();
user.setAvatar("http://g.hiphotos.baidu.com/image/h%3D200/sign=4d3fabc3cbfc1e17e2bf8b317a91f67c/6c224f4a20a446230761b9b79c22720e0df3d7bf.jpg");
user.setName("小米" + i);
user.setAge(String.valueOf(i));
mUsers.add(user);
}
}
}
效果图:
Data Binding大大简化了我们的工作量,值得学习。