RecyclerView 多布局适配器

RecyclerView 多布局适配器

在项目中难免会遇到多种item的列表。功能实现也很简单,大概思路就是通过覆写getItemViewType ,动态的分出类型 然后创建不同的ViewHolder,实现我们的功能。但是这是常规套路,如果item类型太多,难免Adapter代码臃肿,难以维护。就拿目前开发的项目来说,有6种单据,每种单据类型展示的item都不一样。于是,便决定“优化”一下代码。

反复考虑后,我的思路是,将创建和绑定数据这部分业务逻辑抽象出去,通过依赖Adapter原有的“生命周期”来调用具体实现业务逻辑的对象,废话不多说,代码实现也许更直观一些。

首先定义实体模拟一下项目的需求:

`

public abstract class Animal {
    private String name;

    public Animal(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

public class Cat extends Animal {
    public Cat(String name) {
        super(name);
    }
}


public class Dog extends Animal {
    public Dog(String name) {
        super(name);
    }
}

`

我们假设每一种动物为不同的ItemViewType。

然后定义接口

`

public interface Adapter {


    /**
     * 创建适配器
     *
     * @param parent
     * @return
     */
    @NonNull
    RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent);

    /**
     * 绑定数据
     */
    void onBindViewHolder(@NonNull T items, @NonNull RecyclerView.ViewHolder holder, int position);
}

`

具体实现逻辑的Adapter类型

`

public class CatAdapter implements Adapter> {

    @NonNull
    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent) {
        View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_cat, parent, false);
        return new CatViewHolder(view);
    }

    @Override
    public void onBindViewHolder(@NonNull List items, @NonNull RecyclerView.ViewHolder holder, int position) {
        Cat cat = items.get(position);
        ((CatViewHolder) holder).mName.setText(cat.getName());
    }

    static class CatViewHolder extends RecyclerView.ViewHolder {
        TextView mName;

        public CatViewHolder(View itemView) {
            super(itemView);
            mName = itemView.findViewById(R.id.tv_name);
        }
    }
}

public class DogAdapter implements Adapter> {


    @NonNull
    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent) {
        View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_dog, parent, false);
        return new DogViewHolder(view);
    }

    @Override
    public void onBindViewHolder(@NonNull List items, @NonNull RecyclerView.ViewHolder holder, int position) {
        Dog dog = items.get(position);
        ((DogViewHolder) holder).mName.setText(dog.getName());
    }

    static class DogViewHolder extends RecyclerView.ViewHolder {
        TextView mName;

        public DogViewHolder(View itemView) {
            super(itemView);
            mName = itemView.findViewById(R.id.tv_name);
        }
    }
}

`

最后,是主适配器,通过主适配器去实现具体调用

`

public class MainAdapter extends RecyclerView.Adapter {

    private List mAnimals;
    private SparseArrayCompat mCompat;
    private static final int TYPE_CAT = 0;
    private static final int TYPE_DOG = 1;

    public MainAdapter(@Nullable List animals) {
        mAnimals = animals;
        mCompat = new SparseArrayCompat<>();
        mCompat.put(TYPE_CAT, new CatAdapter());
        mCompat.put(TYPE_DOG, new DogAdapter());
    }

    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        return mCompat.get(viewType).onCreateViewHolder(parent);
    }

    @Override
    public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
        Adapter adapter = mCompat.get(holder.getItemViewType());
        adapter.onBindViewHolder(mAnimals, holder, position);
    }

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

    @Override
    public int getItemViewType(int position) {
        if (mAnimals.get(position) instanceof Cat) {
            return TYPE_CAT;
        } else if (mAnimals.get(position) instanceof Dog) {
            return TYPE_DOG;
        }
        return super.getItemViewType(position);
    }
}

public class MainActivity extends AppCompatActivity {
    private RecyclerView mRecyclerView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mRecyclerView = findViewById(R.id.rv_animals);
        mRecyclerView.setLayoutManager(new LinearLayoutManager(this));

        List animals = new ArrayList<>();
        animals.add(new Cat("Tom"));
        animals.add(new Cat("Kit"));
        animals.add(new Dog("mendou"));
        animals.add(new Dog("taidi"));
        animals.add(new Cat("no"));
        mRecyclerView.setAdapter(new MainAdapter(animals));
    }
}

`

ok,可以发现主适配器精简了不少。通过统一的接口,我们把具体的业务逻辑,交给了具体的类去实现,从而达到解耦的目地。

然而,本来到这里我的代码优化已经完成了,但是同事却说,这里的类型判断好讨厌,还得去定义不同的类型。于是,我又想能不能把具体的类型判断也交给具体的类去实现呢?

ok,不妨再讲代码升级一下,让主Adapter更简化一些,其余的工作都交给代理去做。我们不妨定义一个代理类,让它去处理具体该调用哪一个业务类。

这里接口也多加两个函数

`

public interface AdapterDelegate {

    /**
     * 获取类型
     *
     * @return
     */
    int getItemViewType();

    /**
     * 判断是否为当前类型
     *
     * @param items
     * @param position
     * @return
     */
    boolean isForViewType(@NonNull T items, int position);

    /**
     * 创建适配器
     *
     * @param parent
     * @return
     */
    @NonNull
    RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent);

    /**
     * 绑定数据
     */
    void onBindViewHolder(@NonNull T items, int position, @NonNull RecyclerView.ViewHolder holder);
}

`

定义一个抽象类返回具体类型

`

public abstract class AbsAdapterDelegate implements AdapterDelegate {

    public int viewType;

    public AbsAdapterDelegate(int viewType) {
        this.viewType = viewType;
    }

    @Override
    public int getItemViewType() {
        return viewType;
    }
}

`

具体的业务类

`

public class CatAdapter extends AbsAdapterDelegate> {

    public CatAdapter(int viewType) {
        super(viewType);
    }

    @Override
    public boolean isForViewType(@NonNull List items, int position) {
        return items.get(position) instanceof Cat;
    }

    @NonNull
    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent) {
        View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_cat, parent, false);
        return new CatViewHolder(view);
    }

    @Override
    public void onBindViewHolder(@NonNull List items, int position, @NonNull RecyclerView.ViewHolder holder) {
        Cat cat = (Cat) items.get(position);
        ((CatViewHolder) holder).mName.setText(cat.getName());
    }

    static class CatViewHolder extends RecyclerView.ViewHolder {
        TextView mName;

        public CatViewHolder(View itemView) {
            super(itemView);
            mName = itemView.findViewById(R.id.tv_name);
        }
    }
}

public class DogAdapter extends AbsAdapterDelegate> {

    public DogAdapter(int viewType) {
        super(viewType);
    }

    @Override
    public boolean isForViewType(@NonNull List items, int position) {
        return items.get(position) instanceof Dog;
    }

    @NonNull
    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent) {
        View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_dog, parent, false);
        return new DogViewHolder(view);
    }

    @Override
    public void onBindViewHolder(@NonNull List items, int position, @NonNull RecyclerView.ViewHolder holder) {
        Dog dog = (Dog) items.get(position);
        ((DogViewHolder) holder).mName.setText(dog.getName());
    }

    static class DogViewHolder extends RecyclerView.ViewHolder {
        TextView mName;

        public DogViewHolder(View itemView) {
            super(itemView);
            mName = itemView.findViewById(R.id.tv_name);
        }
    }

}

`

业务实现类管理器,主要交给它来处理,具体应该调用哪一个业务类

`

public class AdapterDelegatesManager {

    private SparseArrayCompat> delegates = new SparseArrayCompat<>();

    public void addDelegate(@NonNull AdapterDelegate delegate) {
        int viewType = delegate.getItemViewType();

        if (delegates.get(viewType) != null) {
            throw new IllegalArgumentException("Already registered AdapterDelegate is " + delegates.get(viewType));
        }

        delegates.put(viewType, delegate);
    }

    public int getItemViewType(@NonNull T items, int position) {
        if (items == null) {
            throw new NullPointerException("Items datasource is null!");
        }

        int delegatesCount = delegates.size();

        for (int i = 0; i < delegatesCount; i++) {
            AdapterDelegate delegate = delegates.valueAt(i);
            if (delegate.isForViewType(items, position)) {
                return delegate.getItemViewType();
            }

        }

        throw new IllegalArgumentException(
                "No AdapterDelegate added that matches position=" + position + " in data source");
    }

    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        AdapterDelegate adapterDelegate = delegates.get(viewType);
        if (adapterDelegate == null) {
            throw new NullPointerException("No AdapterDelegate added for ViewType " + viewType);
        }
        return adapterDelegate.onCreateViewHolder(parent);
    }

    public void onBindViewHolder(@NonNull T items,
                                 @NonNull RecyclerView.ViewHolder viewHolder, int position) {
        AdapterDelegate delegate = delegates.get(viewHolder.getItemViewType());

        if (delegate == null) {
            throw new NullPointerException(
                    "No AdapterDelegate added for ViewType " + viewHolder.getItemViewType());
        }
        delegate.onBindViewHolder(items, position, viewHolder);
    }

}

`

最后是我的主Adapter

public class AnimalAdapter extends RecyclerView.Adapter {
    private List mAnimals;
    private AdapterDelegatesManager> mDelegatesManager = new AdapterDelegatesManager<>();

    public AnimalAdapter(List animals) {
        this.mAnimals = animals;
        mDelegatesManager.addDelegate(new DogAdapter(0));
        mDelegatesManager.addDelegate(new CatAdapter(1));
    }

    @Override
    public int getItemViewType(int position) {
        return mDelegatesManager.getItemViewType(mAnimals, position);
    }

    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        return mDelegatesManager.onCreateViewHolder(parent, viewType);
    }

    @Override
    public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
        mDelegatesManager.onBindViewHolder(mAnimals, holder, position);
    }

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

调用

`

public class MainActivity extends AppCompatActivity {
    private RecyclerView mRecyclerView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mRecyclerView = findViewById(R.id.rv_animals);
        mRecyclerView.setLayoutManager(new LinearLayoutManager(this));

        List animals = new ArrayList<>();
        animals.add(new Cat("Tom"));
        animals.add(new Cat("Kit"));
        animals.add(new Dog("mendou"));
        animals.add(new Dog("taidi"));
        animals.add(new Cat("no"));
        mRecyclerView.setAdapter(new AnimalAdapter(animals));
    }
}

`

ok,思路几乎还是不变的。然后通过代理模式让我们的代理类去处理到底该调用哪一个业务类,而具体ViewType也交由具体的业务类去实现。充分达到解耦的目地,更加符合高内聚低耦合的设计规范。

具体代码在这里:https://github.com/qq605088820/delegateadapter.git

你可能感兴趣的:(RecyclerView 多布局适配器)