>昨天寫了一篇「[還在用ListView?](http://blog.csdn.net/cym492224103/article/details/51094982)」講的內容是RecyclerView的使用技巧以及一些常用的開源庫,有朋友反饋“我已經在用recyclerview了”,那么如何讓它更好用呢?此時我想到了優化RecyclerView.Adapter,因為在RecyclerView還沒出來之前我就寫過一篇「[ListView之Adapter優化](http://blog.csdn.net/cym492224103/article/details/38826059)」,通過這篇文章的優化思路可以在原來的代碼上修改部分代碼用在優化RecyclerView.Adapter上,一如既往的好用。
本次主要講兩個方面的優化
- **精簡代碼**
- **擴展功能**
----

###精簡代碼
正常沒優化的寫法:
```java
public class DefAdpater extends RecyclerView.Adapter<DefAdpater.ViewHolder> {
private final List<Status> sampleData = DataServer.getSampleData();
private Context mContext;
public DefAdpater(Context context) {
mContext = context;
}
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View item = LayoutInflater.from(parent.getContext()).inflate(R.layout.tweet, parent, false);
return new ViewHolder(item);
}
@Override
public void onBindViewHolder(ViewHolder holder, int position) {
Status status = sampleData.get(position);
holder.name.setText(status.getUserName());
holder.text.setText(status.getText());
holder.date.setText(status.getCreatedAt());
Picasso.with(mContext).load(status.getUserAvatar()).into(holder.avatar);
holder.rt.setVisibility(status.isRetweet() ? View.VISIBLE : View.GONE);
}
@Override
public int getItemCount() {
return sampleData.size();
}
public static class ViewHolder extends RecyclerView.ViewHolder {
private ImageView avatar;
private ImageView rt;
private TextView name;
private TextView date;
private TextView text;
public ViewHolder(View itemView) {
super(itemView);
text = (TextView) itemView.findViewById(R.id.tweetText);
name = (TextView) itemView.findViewById(R.id.tweetName);
date = (TextView) itemView.findViewById(R.id.tweetDate);
avatar = (ImageView) itemView.findViewById(R.id.tweetAvatar);
rt = (ImageView) itemView.findViewById(R.id.tweetRT);
}
}
}
```
優化后,是這樣的:
```
public class QuickAdapter extends BaseQuickAdapter<Status> {
public QuickAdapter(Context context) {
super(context, R.layout.tweet, DataServer.getSampleData());
}
@Override
protected void convert(BaseAdapterHelper helper, Status item) {
helper.setText(R.id.tweetName, item.getUserName())
.setText(R.id.tweetText, item.getText())
.setText(R.id.tweetDate, item.getCreatedAt())
.setImageUrl(R.id.tweetAvatar, item.getUserAvatar())
.setVisible(R.id.tweetRT, item.isRetweet())
.linkify(R.id.tweetText);
}
}
```
>優化前和優化后的代碼量是3:1的比例!
*我的天啦!太不可思議了!*
現在來分析,如何優化的?**(帶著問題學習)**
思路:
**找到重復部分代碼,抽取到基類,非重復部分用抽象方法代替,具體讓子類實現。**
說了思路在看看具體代碼BaseQuickAdapter里面怎么寫的:
```
@Override
public int getItemCount() {
return data.size();
}
@Override
public BaseAdapterHelper onCreateViewHolder(ViewGroup parent, int viewType) {
View item = LayoutInflater.from(parent.getContext()).inflate(layoutResId, parent, false);
return new BaseViewHolder(context, item);
}
@Override
public void onBindViewHolder(BaseViewHolder holder, final int position) {
convert(holder, data.get(position));
}
protected abstract void convert(BaseViewHolder helper, T item);
```
接下來再看看BaseViewHolder怎么寫的:
```
public class BaseViewHolder extends RecyclerView.ViewHolder {
private final SparseArray<View> views;
private final Context context;
private View convertView;
protected BaseViewHolder(Context context, View view) {
super(view);
this.context = context;
this.views = new SparseArray<View>();
convertView = view;
}
protected <T extends View> T retrieveView(int viewId) {
View view = views.get(viewId);
if (view == null) {
view = convertView.findViewById(viewId);
views.put(viewId, view);
}
return (T) view;
}
public BaseViewHolder setText(int viewId, CharSequence value) {
TextView view = retrieveView(viewId);
view.setText(value);
return this;
}
public BaseViewHolder setImageUrl(int viewId, String imageUrl) {
ImageView view = retrieveView(viewId);
Picasso.with(context).load(imageUrl).into(view);
return this;
}
public BaseViewHolder setVisible(int viewId, boolean visible) {
View view = retrieveView(viewId);
view.setVisibility(visible ? View.VISIBLE : View.GONE);
return this;
}
public BaseViewHolder linkify(int viewId) {
TextView view = retrieveView(viewId);
Linkify.addLinks(view, Linkify.ALL);
return this;
}
//此處省略若干常用賦值常用方法
}
```
>利用SparseArray來做緩存,把常用方法全部寫好,從而避免冗余代碼。
-----
###擴展功能
大家都知道RecyclerView沒有ItemClick方法,可以在上面提過的BaseQuickAdapter里面添加ItemClick,可以這樣寫:
```
private OnRecyclerViewItemClickListener onRecyclerViewItemClickListener;
public void setOnRecyclerViewItemClickListener(OnRecyclerViewItemClickListener onRecyclerViewItemClickListener) {
this.onRecyclerViewItemClickListener = onRecyclerViewItemClickListener;
}
public interface OnRecyclerViewItemClickListener {
public void onItemClick(View view, int position);
}
@Override
public void onBindViewHolder(BaseViewHolder holder, final int position) {
convert(holder, data.get(position));
if (onRecyclerViewItemClickListener != null) {
holder.getView().setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
onRecyclerViewItemClickListener.onItemClick(v, position);
}
});
}
}
```
還可以添加一些常用的方法如:
```
public void remove(int position) {
data.remove(position);
notifyItemRemoved(position);
}
public void add(int position, T item) {
data.add(position, item);
notifyItemInserted(position);
}
```
>代碼我已經上傳到GitHub上了,有興趣的同學Star或者一起共同將它完成的更完善!*送大家一句我非常喜歡的話:不分享誰與你共享呢?*
源碼地址:**[傳送門](https://github.com/CymChad/BaseRecyclerViewAdapterHelper)**