Adapter一定写烦了吧?多种type更是繁琐,修改起来也麻烦,得去Adapter里面各种删东西,逻辑一复杂删个东西都得小心翼翼。。。。。。于是,闲的无聊。写了个简化版的通用可拔插的Adapter,轻喷。。
public class FishAdapter extends RecyclerView.Adapter<Injector.ViewsHolder> {
private @NonNull List<?> items;
private List<Class> mClasses = new ArrayList<>();
private List<Injector> mInjectors = new ArrayList<>();
public FishAdapter() {
this(Collections.emptyList());
}
public FishAdapter(@NonNull List<?> items) {
this.items = items;
}
public void setItems(@NonNull List<?> items) {
this.items = items;
}
public static FishAdapter create() {
return new FishAdapter();
}
public <T> FishAdapter register(Class mClass, Injector mInjector) {
if (mClasses.contains(mClass))
return this;
else {
mClasses.add(mClass);
mInjectors.add(mInjector);
}
return this;
}
@Override
public Injector.ViewsHolder onCreateViewHolder(ViewGroup parent, int viewType) {
return (Injector.ViewsHolder) mInjectors.get(viewType).instance(parent);
}
@Override
public void onBindViewHolder(Injector.ViewsHolder holder, int position) {
int type = holder.getItemViewType();
mInjectors.get(type).onBind(holder, items.get(position));
}
@Override
public int getItemViewType(int position) {
Object item = items.get(position);
return mClasses.indexOf(item.getClass());
}
@Override
public int getItemCount() {
return items == null ? 0 : items.size();
}
public FishAdapter attachTo(RecyclerView mRecyclerView) {
mRecyclerView.setAdapter(this);
return this;
}
}
复制代码
乱取的名字,当时在听周深的大鱼海棠 ,就取了个fishAdapter。。。 应该很容易看懂。 此Adapter的做法是:Adapter相当于只是一个存放 Viewholder、分发Viewholder的地方。不管你多少type ,只要注册进来就行。 好,接下来看绑定视图,一看就知道了,使用原来很熟悉的绑定view的方式。
public abstract class Injector<T> {
public int res;
public Injector(@NonNull @LayoutRes int res) {
this.res = res;
}
public RecyclerView.ViewHolder getViewHolder(ViewGroup mViewGroup) {
View root = LayoutInflater.from(mViewGroup.getContext()).inflate(res, mViewGroup, false);
return new ViewsHolder(root);
}
public abstract void onBind(ViewsHolder mViewsHolder, T mT);
public static class ViewsHolder extends RecyclerView.ViewHolder {
private SparseArray<View> mViews =new SparseArray<>();
public ViewsHolder(View itemView) {
super(itemView);
}
//下面是一系列set方法。。。
public ViewsHolder setText(@IdRes int viewId, CharSequence value) {
TextView view = getView(viewId);
view.setText(value);
return this;
}
public ViewsHolder setText(@IdRes int viewId, @StringRes int strId) {
TextView view = getView(viewId);
view.setText(strId);
return this;
}
public ViewsHolder setAlpha(@IdRes int viewId, float value) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
getView(viewId).setAlpha(value);
} else {
// Pre-honeycomb hack to set Alpha value
AlphaAnimation alpha = new AlphaAnimation(value, value);
alpha.setDuration(0);
alpha.setFillAfter(true);
getView(viewId).startAnimation(alpha);
}
return this;
}
public ViewsHolder setVisible(@IdRes int viewId, boolean visible) {
View view = getView(viewId);
view.setVisibility(visible ? View.VISIBLE : View.GONE);
return this;
}
public ViewsHolder linkify(@IdRes int viewId) {
TextView view = getView(viewId);
Linkify.addLinks(view, Linkify.ALL);
return this;
}
public ViewsHolder setTypeface(@IdRes int viewId, Typeface typeface) {
TextView view = getView(viewId);
view.setTypeface(typeface);
view.setPaintFlags(view.getPaintFlags() | Paint.SUBPIXEL_TEXT_FLAG);
return this;
}
public ViewsHolder setTypeface(Typeface typeface, int... viewIds) {
for (int viewId : viewIds) {
TextView view = getView(viewId);
view.setTypeface(typeface);
view.setPaintFlags(view.getPaintFlags() | Paint.SUBPIXEL_TEXT_FLAG);
}
return this;
}
public ViewsHolder setProgress(@IdRes int viewId, int progress) {
ProgressBar view = getView(viewId);
view.setProgress(progress);
return this;
}
public ViewsHolder setRating(@IdRes int viewId, float rating) {
RatingBar view = getView(viewId);
view.setRating(rating);
return this;
}
public ViewsHolder setOnCheckedChangeListener(@IdRes int viewId, CompoundButton.OnCheckedChangeListener listener) {
CompoundButton view = getView(viewId);
view.setOnCheckedChangeListener(listener);
return this;
}
public ViewsHolder setTag(@IdRes int viewId, Object tag) {
View view = getView(viewId);
view.setTag(tag);
return this;
}
public ViewsHolder setTag(@IdRes int viewId, int key, Object tag) {
View view = getView(viewId);
view.setTag(key, tag);
return this;
}
public ViewsHolder setChecked(@IdRes int viewId, boolean checked) {
View view = getView(viewId);
if (view instanceof Checkable) {
((Checkable) view).setChecked(checked);
}
return this;
}
public <T extends View> T getView(@IdRes int viewId) {
View view = mViews.get(viewId);
if (view == null) {
view = itemView.findViewById(viewId);
mViews.put(viewId, view);
}
return (T) view;
}
}
}
复制代码
这个就更容易看懂了,绑定view。
好了,我们来看下使用方法。
mRecyclerView = (RecyclerView) findViewById(R.id.recycleview);
LinearLayoutManager mLinearLayoutManager = new LinearLayoutManager(this);
mLinearLayoutManager.setOrientation(LinearLayoutManager.VERTICAL);
mRecyclerView.setLayoutManager(mLinearLayoutManager);
mFishAdapter = FishAdapter.create().register(String.class, new Injector<String>(R.layout.layoutone) {
@Override
public void onBind(ViewsHolder mViewsHolder, String mO) {
mViewsHolder.setText(R.id.text, mO);
}
}).register(Test.class, new Injector<Test>(R.layout.layouttwo) {
@Override
public void onBind(ViewsHolder mViewsHolder, Test mO) {
mViewsHolder.setText(R.id.text, mO.name);
mViewsHolder.setText(R.id.text2,mO.name+"LOL");
}
})
.attachTo(mRecyclerView);
for (int i = 0; i < 10; i++) {
items.add("爱情公寓" + i);
}
for (int i = 0; i < 10; i++) {
items.add(new Test("爱情公寓视图" + i));
}
mFishAdapter.setItems(items);
mFishAdapter.notifyDataSetChanged();
复制代码
总结一下:代码一路写过来,慢慢意识到我们在写代码的时候, 组合有可能很多时候打大于继承,拔插式的设计更容易代码的修改维护。demo就不贴了。就上面2个类就没了。 此Adapter 只是随手写的简化版,有很多地方可以完善,github也有十分完善的第三方库,比如:github.com/drakeet/Mul…。谢谢阅读。