大家还记得当前大明上湖畔的的 BaseAdapterHelper 么?哈,开个玩笑哈,应该是 GitHub的 BaseAdapterHelper哈。
关于 BaseAdapterHelper 介绍以及详细用法,我就不在这篇博文里就介绍了。
附上 BaseAdapterHelper 的连接:base-adapter-helper
大家都知道,BaseAdapterHelper是用在 ListView 以及 GrildView 中一个很强大的第三方库。用了这个库之后,相信大家都在开发中节省了相当多的时间。
相信大家现在都在慢慢在项目中开始使用 RecyclerView 了吧。RecyclerView 与 ListView 和 GridView相当的类似,都是能在有限的屏幕空间里展示大量的数据集。但是 RecyclerView 又以高度解耦的特征深受开发者喜爱。虽然RecyclerView 与 ListView 等列表控年有一定的类似(都要 Adapter),但是安卓给我们提供的Adapter 的基类又是不一样的。(关于 RecyclerView 的基本使用,我这里就不做介绍了,大家可以在 csdn上找一找。),那么,我们之前的 BaseAdapterHelper 是不是就不能用了。
所以,我们开始打造RecyclerView 的 BaseAdapterHolder.
其实,思路还是跟 BaseAdapter 比较类似的。
一:先创建一个 RecyclerView 的简单工程:
首先,我们看一下布局:
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<android.support.v7.widget.RecyclerView
android:id="@+id/rlv"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
RelativeLayout>
然后是我们MainActivity.java
package wu.yul.baseadater4recyclerview;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import java.util.ArrayList;
import java.util.List;
import wu.yul.baseadater4recyclerview.adapter.CommonAdapter;
public class MainActivity extends AppCompatActivity {
private RecyclerView rlv;
private RecyclerView.LayoutManager mLayoutManager;
private CommonAdapter mCommonAdapter;
private List mList;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initialize();
}
protected void onResume() {
super.onResume();
}
private void initialize() {
rlv = (RecyclerView) findViewById(R.id.rlv);
mLayoutManager = new LinearLayoutManager(getApplicationContext());
mList = new ArrayList<>();
for(int i=0;i<10;i++){
mList.add("TestData"+i);
}
mCommonAdapter = new CommonAdapter(mList);
rlv.setLayoutManager(mLayoutManager);
rlv.setAdapter(mCommonAdapter);
}
}
然后我们来观察一下 CommonAdapter:
*/
public class CommonAdapter extends RecyclerView.Adapter<CommonAdapter.BaseViewHolder> {
public List mDataSet;
public CommonAdapter(List list){
mDataSet =list;
}
public CommonAdapter.BaseViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_rlv, parent, false);
return new BaseViewHolder(view);
}
public void onBindViewHolder(CommonAdapter.BaseViewHolder holder, int position) {
holder.tv.setText(mDataSet.get(position));
}
public int getItemCount() {
return mDataSet.size();
}
class BaseViewHolder extends RecyclerView.ViewHolder {
private TextView tv;
public BaseViewHolder(View itemView) {
super(itemView);
tv = (TextView) itemView.findViewById(R.id.tv);
}
}
}
二:改造第一步:提取布局
首先,我们可以看到,在 onCreateViewHolder 里面,变化的就布局以及返回的 Holder 了。但是我们要做是万能的 ViewHolder,所以,其实返回值也是不变的。那我们就把 布局提取出来。改造一下构造函数。
public CommonAdapter(List list,int resID){
mDataSet =list;
this.resID =resID;
}
以及 OnCreateViewHolder:
public CommonAdapter.BaseViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(resID, parent, false);
return new BaseViewHolder(view);
}
三:onBindViewHolder:
相信大家都知道,在 onBindViewHolder 中,我们把数据与相应的控件进行绑定。而在之前的 BaseAdapterHelper 中,正是把这一个绑定的操作,放在具体的实现类中。那么,我们的思路就比较清晰了。同样,写一个虚函数,并且在 onBindViewHolder中调用。
public void onBindViewHolder(CommonAdapter.BaseViewHolder holder, int position) {
convert(holder, mDataSet.get(position));
}
public abstract void convert(BaseViewHolder holder, String string);
接下来我们再把内部类 BaseViewHolder 给提取出来,让他集成 RecyclerView.ViewHolder。
public class BaseViewHolder extends RecyclerView.ViewHolder {
private Context mContext;
private int position;
private final SparseArray views;
private View rootView;
public BaseViewHolder(View itemView) {
super(itemView);
rootView = itemView;
mContext = itemView.getContext();
position = getLayoutPosition();
views = new SparseArray<>();
}
}
其中,mContext 是用于后期用于加载图片时要用的。views 用于存储后续存放我们从视图中取得的控件。我们写一个 getView 的方法。用于取得对应的控件、
public View getView(int resID){
View view = views.get(resID);
if(null==view){
view = rootView.findViewById(resID);
views.put(resID,view);
}
return view;
}
不过这里,再进行一下改造。因为我们取得的是一个 View,而不是具体的 View 的子类。那么做一个简单的变更就好了。
public T getView(int resID){
View view = views.get(resID);
if(null==view){
view = rootView.findViewById(resID);
views.put(resID,view);
}
return (T)view;
}
然后我们写一个 setText 的方法:
public BaseViewHolder setText(int viewID,int resID){
TextView view = getView(resID);
view.setText(resID);
return this;
}
附一个 BaseViewHolder 的完整代码:
public class BaseViewHolder extends RecyclerView.ViewHolder {
private Context mContext;
private int position;
private final SparseArray views;
private View rootView;
public BaseViewHolder(View itemView) {
super(itemView);
mContext = itemView.getContext();
position = getLayoutPosition();
views = new SparseArray<>();
rootView = itemView;
}
public T getView(int viewID) {
View view = views.get(viewID);
if (null == view) {
view = rootView.findViewById(viewID);
views.put(viewID, view);
}
return (T) view;
}
public BaseViewHolder setText(int viewID, int resID) {
TextView view = getView(resID);
view.setText(resID);
return this;
}
public BaseViewHolder setText(int viewID, String text) {
TextView view = getView(viewID);
view.setText(text);
return this;
}
}
那我们回到 MainActivity 中,看看怎么调用:
mCommonAdapter = new CommonAdapter(mList,R.layout.item_rlv) {
public void convert(BaseViewHolder holder, String string) {
holder.setText(R.id.tv,string);
}
};
是不是跟我们的之前的BaseAdapterHelper 基本一样啦。最后我们改造 CommonAdapter:
public abstract class CommonAdapter extends RecyclerView.Adapter {
public List mDataSet;
public final int resID;
public CommonAdapter(List list, int resID) {
mDataSet = list;
this.resID = resID;
}
public BaseViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(resID, parent, false);
return new BaseViewHolder(view);
}
public void onBindViewHolder(BaseViewHolder holder, int position) {
convert(holder, mDataSet.get(position));
}
public abstract void convert(BaseViewHolder holder, T t);
public int getItemCount() {
return mDataSet.size();
}
}
这样,我们就可以传任意类型的 List 了。当然,BaseViewHolder里还可以加更多复杂的操作,我就不详细介绍了。大家可以参考 文首的 BaseAdapterHelper.
源码:BaseViewHolder