Как сделать несколько типов представления в RecyclerView, используя две модели данных? - PullRequest
1 голос
/ 31 октября 2019

У меня есть данные, которые я получаю от API с помощью библиотеки Retrofit. API работает отлично. Проблема в том, как поместить данные в список и отобразить их с помощью адаптера RecyclerView. Я пытался использовать HashMap, но это приведет к сбою приложения. Может кто-нибудь помочь мне показать правильную структуру и решение этой проблемы?

Данные из API

Модель отчета

Запись модели в списке отчетов

Данные Iуже получил от API

Интерфейс, который я хочу отобразить

Ответы [ 2 ]

1 голос
/ 02 ноября 2019

Я предлагаю вам Свести модель . Вместо того чтобы иметь родителя с ребенком, имейте только один уровень. Кроме того, использует различные модели данных для вашего пользовательского интерфейса и для модернизации . При необходимости, конвертировать между моделями. Таким образом, вещи не будут тесно связаны, и вы можете делать другие вещи при покрытии, например, форматировать строки при необходимости.

// This is what the data model will extend
interface UiBaseModel { }

// monthly detail report
class UiMonthlyDetailReport implements UiBaseModel {

    private String month;
    private String total;

    UiMonthlyDetailReport(String month, String total) {
        this.month = month;
        this.total = total;
    }

    public String getMonth() {
        return month;
    }

    public String getTotal() {
        return total;
    }
}

// monthly detail record
class UiMonthlyDetailsRecord implements UiBaseModel {

    private String month;
    private String expenseName;
    private String expenseIcon;
    private String expenseTotal;

    UiMonthlyDetailsRecord(String month, String expenseName, String expenseIcon, String expenseTotal) {
        this.month = month;
        this.expenseName = expenseName;
        this.expenseIcon = expenseIcon;
        this.expenseTotal = expenseTotal;
    }

    public String getMonth() {
        return month;
    }

    public String getExpenseName() {
        return expenseName;
    }

    public String getExpenseIcon() {
        return expenseIcon;
    }

    public String getExpenseTotal() {
        return expenseTotal;
    }
}



// In your activity / fragment / viewmodel / presenter:

    List<ReportMonthlyDetailsReport> reports = ... // get your data from retrofit
    List<UiBaseModel> uiModels = ArrayList<UiBaseModel>();
    for (ReportMonthlyDetailsReport report : reports) {
        // First records, then report
        List<ReportMonthlyDetailsRecord> records = report.getRecords();
        for (ReportMonthlyDetailsRecord record : records) {
            // Create UI model and add to list
            UiMonthlyDetailsRecord uiRecord = UiMonthlyDetailsRecord(record.getMonth_label(), record.getExpense_type_name(), record.getExpense_type_icon(), record.getExpense_type_total());
            uiModels.add(uiRecord);
        }
        // Lastly, add the report
        UiMonthlyDetailsReport uiReport = UiMonthlyDetailsReport(report.getMonth_label(), report.getMonthly_total());
        uiModels.add(uiReport);
    }

    // Use the ui models (for the recycler adapter)
    MonthlyDetailsAdapter adapter = MonthlyDetailsAdapter(uiModels);
    recyclerView.adapter = adapter;

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

public class MonthlyDetailsAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {

    private final static int VIEW_TYPE_RECORD = 0;
    private final static int VIEW_TYPE_REPORT = 1;

    private List<UiBaseModel> data;

    MonthlyDetailsAdapter(List<UiBaseModel> data) {
        this.data = data;
    }

    class RecordViewHolder extends RecyclerView.ViewHolder {
        public RecordViewHolder(@NonNull View itemView) {
            // code
            super(itemView);
        }
    }

    class ReportViewHolder extends RecyclerView.ViewHolder {
        public ReportViewHolder(@NonNull View itemView) {
            // code
            super(itemView);
        }
    }

    @Override
    public int getItemViewType(int position) {
        UiBaseModel item = data.get(position);
        if (item instanceof UiMonthlyDetailsRecord) {
            return VIEW_TYPE_RECORD;
        } else {
            return VIEW_TYPE_REPORT;
        }
    }

    @Override
    public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
        if (holder instanceof RecordViewHolder) {
            UiMonthlyDetailsRecord record = (UiMonthlyDetailsRecord) data.get(position);
            // bind record
        } else if (holder instanceof ReportViewHolder) {
            UiMonthlyDetailsReport report = (UiMonthlyDetailsReport) data.get(position);
            // bind report
        }
    }
}
0 голосов
/ 31 октября 2019
  1. переопределить getItemViewType(position: Int) и вернуть другой тип с другой моделью.
  2. переопределить onCreateViewHolder(parent: ViewGroup, viewType: Int), вы можете создать itemViewHolder в соответствии с itemType.
  3. переопределить onBindViewHolder(holder: BaseViewHolder, position: Int), выможет отображать то, что вам нужно. не забудьте оценить элемент itemType

В общем, вам нужно создать другой тип элемента в соответствии с вашей моделью, затем создать другой видоискатель и, наконец, отобразить видовой элемент вместе с вашей моделью

...