Search
Write a publication
Pull to refresh
2
0
Виктор Земцов @ZemtsovVU

Android Team Lead

Send message
По-моему, второй вариант смотрится тоже не особо красиво


Ребят, ну надо понимать что в статье используется максимально упрощенная модель. Все описано в одном классе, используется enum и т.д. Это сделано умышленно для упрощения восприятия идеи. Как вы реализуете эту идею — уже другой вопрос.

Вот как выглядит моя боевая реализация:

Вариант боевой реализации идеи
public class UsersArbitraryCellAdapter extends ArbitraryCellAdapter {

    public UsersArbitraryCellAdapter() {
        this.arbitraryCellSelector.addCell(new ProgressArbitraryCell());
        this.arbitraryCellSelector.addCell(new AdArbitraryCell());
        this.arbitraryCellSelector.addCell(new UserArbitraryCell());
    }

    public void setUsers(List<UserVo> userList) {
		// Set users, ads, progress...
    }
}

public abstract class ArbitraryCellAdapter
		extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
    protected ArbitraryCellSelector arbitraryCellSelector = new ArbitraryCellSelector();
    protected List itemList = new ArrayList();

    @Override
    public final int getItemViewType(int position) {
        return arbitraryCellSelector.getCell(itemList.get(position)).type();
    }

    @Override
    public final RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        return arbitraryCellSelector.getCell(viewType).holder(parent);
    }

    @Override
    public final void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
        Object item = itemList.get(position);
        arbitraryCellSelector.getCell(item).bind(holder, item);
    }

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

public abstract class ArbitraryCellHolder<T> extends RecyclerView.ViewHolder {

    public ArbitraryCellHolder(View itemView) {
        super(itemView);
        ButterKnife.bind(this, itemView);
    }

    public abstract void bind(T item);
}

public final class ArbitraryCellSelector {
    private List<Cell> cellList = new ArrayList<>();

    public void addCell(Cell cell) {
        cellList.add(cell);
    }

    public void removeCell(Cell cell) {
        cellList.remove(cell);
    }

    public Cell getCell(Object item) {
        for (Cell cell : cellList) {
            if (cell.is(item)) {
                return cell;
            }
        }
        throw new NoSuchRecyclerRowException();
    }

    public Cell getCell(int viewType) {
        for (Cell cell : cellList) {
            if (cell.type() == viewType) {
                return cell;
            }
        }
        throw new NoSuchRecyclerRowException();
    }

    public interface Cell {

        boolean is(Object item);

        int type();

        RecyclerView.ViewHolder holder(ViewGroup parent);

        void bind(RecyclerView.ViewHolder holder, Object item);
    }
}

public class AdArbitraryCell implements ArbitraryCellSelector.Cell {

    @Override
    public boolean is(Object item) {
        return item instanceof AdVo;
    }

    @Override
    public int type() {
        return R.layout.cell_ad;
    }

    @Override
    public RecyclerView.ViewHolder holder(ViewGroup parent) {
        LayoutInflater inflater = LayoutInflater.from(parent.getContext());
        View view = inflater.inflate(R.layout.cell_ad, parent, false);
        return new AdViewHolder(view);
    }

    @Override
    public void bind(RecyclerView.ViewHolder holder, Object item) {
        try {
            AdViewHolder adViewHolder = (AdViewHolder) holder;
            AdVo ad = (AdVo) item;
            adViewHolder.bind(ad);
        } catch (ClassCastException e) {
            L.printStackTrace(e);
        }
    }

    protected class AdViewHolder extends ArbitraryCellHolder<AdVo> {
        @BindView(R.id.ad_text_view)
        protected TextView adTextView;

        public AdViewHolder(View itemView) {
            super(itemView);
        }

        @Override
        public void bind(AdVo item) {
            adTextView.setText(item.getTitle());

            itemView.setOnClickListener(view -> adPublishSubject.onNext(item));
        }
    }
}

// Other ArbitraryCells...



Про Adapter Delegates автор не слышал?


Действительно не слышал. Как и многие другие, исходя из моего немалого опыта и оценки статьи сообществом.

Решение изящное, признаю. Что использовать у себя в проекте — импортировать библиотеку или написать один вспомогательный класс ArbitraryCellSelector — дело личного каждого.
Еще я бы избавился от неявных зависимостей и вынес весь класс CellType наружу.


В боевых условиях именно так и делается :)

Цель статьи — максимально просто и доступно донести идею. А как вы это реализуете под себя — вопрос десятый.
В идеале от класса CellType нужно избавляться. Точнее заменять его на не статичный объект. Не секрет, что enum в Java является статичным объектом, а статика может в определенных ситуациях стать головной болью и причиной падений.

В статье enum использован для упрощения материала и простоты восприятия идеи. С этой же цель явно прописаны все методы в контракте enum и локальные переменные.
Все правильно, именно такой подход позволяет избавиться от проверок на тип и преобразований типов. И это самый очевидный подход для решения этой задачи.

Но как вы правильно заметили, у этого подхода есть один недостаток. Под каждый адаптер нам потребуется столько классов-оберток, сколько разнотипных ячеек планируется использовать. Плюс под каждый такой адаптер (а точнее для классов-оберток под текущий адаптер) в идеале создается еще и интерфейс.

Плюс только лишь оборачивание не решает всех поставленных вопросов.
Я сторонник «тонких» моделей. Т.е. модель здесь понимается в самом узком смысле — это просто DataObject. И вся его обязанность сводится к тому, чтобы предоставлять нам доступ к данным. Если обязать этот объект заниматься обработкой самого себя, то это уже будет нарушением принципа SRP.

Но такой подход возможен. И даже может позволить избежать проверок на тип и приведений типов.

Information

Rating
Does not participate
Location
Новосибирск, Новосибирская обл., Россия
Date of birth
Registered
Activity