用组合模式巧妙实现recycleview多类型

483 阅读2分钟

软件设计模式中,很多时候组合是优于继承的,组合模式相对来说更加解耦,也更方便维护 recycleview里面的多类型就可以用组合来实现 更方便的修改、维护

一个小demo 说一下思路,实现多类型的同时也是个通用的adapter

class BaseViewHolder : RecyclerView.ViewHolder {

    private val views = SparseArray<View>()//保存view

    constructor(view: View, convert: LightAdapter.Convert) : super(view) {
        this.convert = convert
    }

    fun getView(@IdRes viewId: Int): View? {
        var view: View? = views.get(viewId)
        if (view == null) {
            view = itemView.findViewById(viewId)
            views.put(viewId, view)
        }
        return view
    }

    fun setText(viewId: Int, text: String): BaseViewHolder {
        var mTextView = getView(viewId) as TextView
        mTextView.text = text
        return this

    }

    var convert: LightAdapter.Convert;
}
public class LightAdapter extends RecyclerView.Adapter<BaseViewHolder> {

    private @NonNull
    List<?> items;
    private List<Class> mTypes = new ArrayList<>();  //数据类型
    private List<Integer> mLayouts = new ArrayList<>();  //布局类型
    private List<Convert> mConverts = new ArrayList<>(); //布局对应的绑定

    public LightAdapter register(@LayoutRes int layout, Class mClass, Convert mConvert) {
        mTypes.add(mClass);
        mLayouts.add(layout);
        mConverts.add(mConvert);
        return this;
    }

    public LightAdapter() {
        this(Collections.emptyList());
    }

    public LightAdapter(List<?> items) {
        this.items = items;
    }

    @Override
    public int getItemViewType(int position) {
        return mTypes.indexOf(items.get(position).getClass()); //判断类型
    }

    @NonNull
    @Override
    public BaseViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {

        View itemView = LayoutInflater.from(parent.getContext()).inflate(mLayouts.get(viewType), parent, false);
        return new BaseViewHolder(itemView, mConverts.get(viewType));
    }

    @Override
    public void onBindViewHolder(@NonNull BaseViewHolder holder, int position) {
        holder.convert.convert(holder, position);
    }

    @Override
    public int getItemCount() {
        return items.size();
    }


    public interface Convert {
        void convert(BaseViewHolder mBaseViewHolder, int position);
    }

}

写的很简单,就2个类 加起来估计150行代码 实现了多类型/单类型的可拔插链式调用,通用的adapter

代码特别特别简单

使用方式就更简单了:

class MainActivity : BaseActivity() {

    private lateinit var mLightAdapter: LightAdapter
    private var list = mutableListOf<Any>()

    override fun getToolbar(): Toolbar? {
        return null
    }

    override fun initView(mSavedInstanceState: Bundle?) {

        list.add(Testone("ttttt"))
        list.add(TestTwo("2342423424"))
        list.add(TestThree("two"))
        list.add(Testone("fsdfsf"))
        list.add(TestTwo("twy567686o"))
        list.add(TestThree("two"))
        list.add(Testone("hjkfgh"))
        list.add(TestTwo("867867"))
        list.add(TestThree("two"))
        list.add(Testone("个"))
        list.add(TestTwo("645465464"))
        list.add(TestThree("two"))
        list.add(Testone("过分"))
        list.add(TestTwo("78674567gh"))
        list.add(TestThree("two"))
        
        mLightAdapter = LightAdapter(list)
        .register(R.layout.one, Testone::class.java, LightAdapter.Convert { mBaseViewHolder, position ->

                        //   todo something
        })
         .register(R.layout.two, TestTwo::class.java, object : LightAdapter.Convert {
                    override fun convert(mBaseViewHolder: BaseViewHolder?, position: Int) {
                        //   todo something
                        (mBaseViewHolder?.getView(R.id.yyy) as TextView).text = list.get(position).toString()
                    }
                })
        .register(R.layout.three, TestThree::class.java, LightAdapter.Convert { mBaseViewHolder, position ->
                    //   todo something
                })
                
        recyclerview.layoutManager = LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false)
        recyclerview.adapter = mLightAdapter
    }

    override fun getContentViewLayoutID(): Int {
        return R.layout.activity_main2
    }

    override fun getLoadingTargetView(): View? {
        return null

    }


}

完成~当你想去掉某个类型直接删掉那个注册类型就行 再也不用小心翼翼的在adapter里面判断类型,各种删除修改东西。。。同时也少了写了很多类 提一下经常用到的 header footer,加载更多,其实都是多类型的实现 ,这里只需要注册一个type 就是一个header/footer,