Java 如何使用两个数据模型在RecyclerView中创建多视图类型?
我有我使用改型库从API获得的数据。API工作得很好。问题是如何将数据放入列表并使用RecyclerView适配器显示它。我尝试使用HashMap,但它会使应用程序崩溃。有人能帮我展示这个问题的正确结构和解决方案吗 来自API的数据 报告模型 在报告列表中记录模型 我已经从API获得了数据 我要显示的界面Java 如何使用两个数据模型在RecyclerView中创建多视图类型?,java,android,api,android-recyclerview,retrofit,Java,Android,Api,Android Recyclerview,Retrofit,我有我使用改型库从API获得的数据。API工作得很好。问题是如何将数据放入列表并使用RecyclerView适配器显示它。我尝试使用HashMap,但它会使应用程序崩溃。有人能帮我展示这个问题的正确结构和解决方案吗 来自API的数据 报告模型 在报告列表中记录模型 我已经从API获得了数据 我要显示的界面 覆盖getItemViewType(位置:Int)并返回不同型号的不同类型 覆盖CreateViewHolder(父级:ViewGroup,viewType:Int),您可以根据it
getItemViewType(位置:Int)
并返回不同型号的不同类型itemType
通常,您需要根据您的模型创建不同的itemtype,然后创建不同的viewholder,最后使用您的模型显示viewholder我建议您将模型展平。不要让父母和孩子在一起,而要只有一个级别。另外,为用户界面和改装使用不同的数据模型。需要时,在模型之间进行转换。这样,事情就不会紧密耦合,在转换时可以做其他事情,例如,如果需要,格式化字符串
// 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;
//这就是数据模型将要扩展的内容
接口UiBaseModel{}
//每月详细报告
类UiMonthlyDetailReport实现UiBaseModel{
私人串月;
私有字符串总数;
UiMonthlyDetailReport(字符串月份,字符串总数){
本月=月;
这个.总计=总计;
}
公共字符串getMonth(){
返回月份;
}
公共字符串getTotal(){
返回总数;
}
}
//每月详细记录
类UiMonthlyDetailsRecord实现UiBaseModel{
私人串月;
私有字符串expenseName;
私人字符串支出图标;
私人字符串支出总额;
UiMonthlyDetailsRecord(字符串月份、字符串费用名称、字符串费用图标、字符串费用总计){
本月=月;
this.expenseName=expenseName;
this.expensecon=expensecon;
this.expenseTotal=expenseTotal;
}
公共字符串getMonth(){
返回月份;
}
公共字符串getExpenseName(){
返回expenseName;
}
公共字符串getExpenseIcon(){
返回费用图标;
}
公共字符串getExpenseTotal(){
返回费用总额;
}
}
//在活动/片段/视图模型/演示者中:
列表报告=…//从改装中获取数据
List uiModels=ArrayList();
对于(ReportMonthlyDetailsReport:报告){
//先记录,然后报告
列表记录=report.getRecords();
for(ReportMonthlyDetailsRecord记录:记录){
//创建UI模型并添加到列表
UiMonthlyDetailsRecord uiRecord=UiMonthlyDetailsRecord(record.getMonth_label(),record.getExpense_type_name(),record.getExpense_type_icon(),record.getExpense_type_total());
uiModels.add(uiRecord);
}
//最后,添加报告
UiMonthlyDetailsReport uiReport=UiMonthlyDetailsReport(report.getMonth\u label(),report.getMonthly\u total());
uiModels.add(uiReport);
}
//使用ui模型(用于回收器适配器)
MonthlyDetailsAdapter适配器=MonthlyDetailsAdapter(uiModels);
recyclerView.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
}
}
}
公共类MonthlyDetailsAdapter扩展了RecyclerView.Adapter{
私有最终静态int视图\类型\记录=0;
私有最终静态int视图\类型\报告=1;
私人名单数据;
MonthlyDetailsAdapter(列表数据){
这个数据=数据;
}
类RecordViewHolder扩展了RecyclerView.ViewHolder{
public RecordViewHolder(@NonNull View itemView){
//代码
超级(项目视图);
}
}
类ReportViewHolder扩展了RecyclerView.ViewHolder{
public ReportViewHolder(@NonNull View itemView){
//代码
超级(项目视图);
}
}
@凌驾
public int getItemViewType(int位置){
UiBaseModel项=data.get(位置);
if(UiMonthlyDetailsRecord的项目实例){
返回视图\类型\记录;
}否则{
返回视图类型报告;
}
}
@凌驾
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder,int位置){
if(RecordViewHolder的持有者实例){
UiMonthlyDetailsRecord记录=(UiMonthlyDetailsRecord)数据。获取(位置);
//绑定记录
}else if(ReportViewHolder的持有者实例){
UiMonthlyDetailsReport report=(UiMonthlyDetailsReport)data.get(position);
//装订报告
}
}
}
问题是如何区分getItemViewType中的子项和父项?私有列表数据总量@重写列表中的公共int-getItemViewType(int-position){if(TextUtils.isEmpty(dataTotal.get(position).getMonthly\u-total()){return-TYPE\u-PARENT;}否则{return-TYPE\u-CHILD;}},还有另一个记录列表,它是报表列表的子项####################您可以创建一个包装器实体,并创建一个类似于
列表
数据类包装器的列表(val records:YourEntity,val report:YourEntity,val itemType,val itetype: