通用Adapter设计,SparseArray+泛型+回调的使用

时间:2023-03-09 04:08:22
通用Adapter设计,SparseArray+泛型+回调的使用

看到题目,我相信聪明的各位已经有一定想法了。
一个Adapter,最简单的优化就是使用泛型,他可以省去非常多的代码,不过在此之上,我们还可以继续优化,优化他的好基友是:ViewHolder。
在过去,我们通常使用一个内部类来写ViewHolder,换一种思路,我们用集合来设计ViewHolder,集合的泛型指定为View,这样ViewHolder就变成通用的了。
原理知道了,后面只剩下代码逻辑问题了。
(注:特别复杂的Listview或者RecycleView不适用,用集合替换ViewHolder,因为算法难度增加了,页面加载效率相对降低了,可能会出现页面抖动的情况)

源码:

使用情况:

public class ListRecycle extends AppCompatActivity {
private RecyclerView recyclerView;
private List<String> mDatas; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_list_recycle);
recyclerView = (RecyclerView) findViewById(R.id.list_recycle_rv); initData();
LinearLayoutManager layoutManager = new LinearLayoutManager(ListRecycle.this);
recyclerView.setLayoutManager(layoutManager);
layoutManager.setOrientation(OrientationHelper.VERTICAL); //使用情况就跟写按钮点击事件一样
//指定泛型:String
//参数:上下文,
// Item的布局Id,
// List(泛型和Adapter相同:String)
recyclerView.setAdapter(new MyRecycleAdapter<String>(ListRecycle.this,
R.layout.activity_list_recycle_item, mDatas) {
@Override
void bindView(MyViewHolder holder, String obj) {
holder.setText(R.id.list_recycle_item_txt, obj);
}
});
recyclerView.setItemAnimator(new DefaultItemAnimator()); } private void initData() {
mDatas = new ArrayList<String>();
for (int i = 0; i < 40; i++) {
mDatas.add("item" + i);
}
}
}

实现类(以RecycleView的Adapter为例):

**
* Created by ChenSS on 2016/9/21.
*/
public abstract class MyRecycleAdapter<T> extends RecyclerView.Adapter<MyRecycleAdapter.MyViewHolder> {
//个人喜欢List
private List<T> mData;
private LayoutInflater mLayoutInflater;
//Item的布局Id
private int mLayoutRes; public MyRecycleAdapter(Context context, int mLayoutRes, List<T> mData) {
this.mData = mData;
this.mLayoutRes = mLayoutRes;
mLayoutInflater = LayoutInflater.from(context);
} @Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = mLayoutInflater.inflate(mLayoutRes, null, false);
return new MyViewHolder(view);
} @Override
public void onBindViewHolder(MyViewHolder holder, int position) {
//调用我们自己的回调方法
this.bindView(holder, mData.get(position));
} //这个就是要回调的方法,其实也可以考虑回调onBindViewHolder的,但是自己写更灵活一些,参数可以自己指定,还可以考虑加别的
abstract void bindView(MyRecycleAdapter.MyViewHolder holder, T obj); @Override
public int getItemCount() {
return mData != null ? mData.size() : 0;
} public static class MyViewHolder extends RecyclerView.ViewHolder {
//另一个关键点,集合,这个集合跟Map类似,效率比Map高
private SparseArray<View> mViews;
//RecycleView的一个item
private View item;
private static MyViewHolder sHolder = null; public MyViewHolder(View itemView) {
super(itemView);
item = itemView;
mViews = new SparseArray<>();
} /**
* 最后一个关键点,封装findViewById,使用我们自己的
*
* @param id
* @param <T>
* @return
*/
@SuppressWarnings("unchecked")
public <T extends View> T findView(int id) {
T t = (T) mViews.get(id);
if (t == null) {
t = (T) item.findViewById(id);
mViews.put(id, t);
}
return t;
} /**
* 直接返回当前item,比如说:给Item添加点击事件,就不要用其它接口回调什么的了,已经用了其它回调,再用就太乱了
*/
public View getItemView() {
return item;
} /**
* 设置文字
*/
public MyViewHolder setText(int id, CharSequence text) {
View view = findView(id);
if (view instanceof TextView) {
((TextView) view).setText(text);
}
return this;
} /**
* 设置点击监听
*/
public MyViewHolder setOnClickListener(int id, View.OnClickListener listener) {
findView(id).setOnClickListener(listener);
return this;
}
}
}