首页 > 解决方案 > 如何使用 Retrofit 和 ViewModel 制作 RecyclerView 多个 ViewType

问题描述

最近我在这个视频之后创建了具有多个 ViewTypes 的 RecyclerView 。在视频中,讲师遵循了在 MainAvtivity 中使用 ArrayList 发送数据的传统方法。但是当我使用 ViewModel 和 Retrofit 时,它没有传递任何数据,屏幕上也没有显示任何内容

这里是我所做的赎罪祭。

第一的:

我有 3 种不同类型的视图,所以我为每个视图创建了 3 个模型类(FirstImageModelLiveModelDailyImageModel)。

FirstImageModel ——所有其他 2 个类都有相同的担架。

public class FirstImageModel {

@SerializedName("firstImageUrl")
private String firstImageUrl;

public FirstImageModel(String firstImageUrl) {
    this.firstImageUrl = firstImageUrl;
}

public String getFirstImageUrl() {
    return firstImageUrl;
}

public void setFirstImageUrl(String firstImageUrl) {
    this.firstImageUrl = firstImageUrl;
}

我创建了第四个名为ItemModel的类,其类型为 int 和 Object 对象。

public class ItemModel {

private int type;
private Object object;

public ItemModel(int type) {
    this.type = type;
    this.object = object;
}

public int getType() {
    return type;
}

public void setType(int type) {
    this.type = type;
}

public Object getObject() {
    return object;
}

public void setObject(Object object) {
    this.object = object;
    }
}

第二:

我创建了一个名为HomeAdapter的适配器类,它从 RecyclerView 扩展而来,并且我在同一个类HomeAdapter中为eatch 视图创建了 3 个类。

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

private List<ItemModel> items;

public HomeAdapter(List<ItemModel> items) {
    this.items = items;
}

public void setHomeList(List<ItemModel> items) {
    this.items = items;
    notifyDataSetChanged();
}

@NonNull
@Override
public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {

    // Here is types are: 0-FirstImage, 1-Live, 2-DailyImage
    if (viewType == 0) {
        return new FirstImageViewHolder(
                LayoutInflater.from(parent.getContext()).inflate(
                        R.layout.item_home_container_firstimage,
                        parent,
                        false
                )
        );
    } else if (viewType == 1) {
        return new LiveViewHolder(
                LayoutInflater.from(parent.getContext()).inflate(
                        R.layout.item_home_container_live,
                        parent,
                        false
                )
        );
    } else {
        return new DailyImageViewHolder(
                LayoutInflater.from(parent.getContext()).inflate(
                        R.layout.item_home_container_dailyimage,
                        parent,
                        false
                )
        );
    }
}

@Override
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {

    if (getItemViewType(position) == 0) {
        FirstImageModel firstImageModel = (FirstImageModel) items.get(position).getObject();
        ((FirstImageViewHolder) holder).setFirstImageData(firstImageModel);

    } else if (getItemViewType(position) == 1) {
        LiveModel liveModel = (LiveModel) items.get(position).getObject();
        ((LiveViewHolder) holder).setLiveImageData(liveModel);

    } else {
        DailyImageModel dailyImageModel = (DailyImageModel) items.get(position).getObject();
        ((DailyImageViewHolder) holder).setDailyImageData(dailyImageModel);
    }
}

@Override
public int getItemCount() {
    if(this.items != null) {
        return this.items.size();
    }
    return 0;
}

@Override
public int getItemViewType(int position) {
    return items.get(position).getType();
}

/* firstImage Adapter */
static class FirstImageViewHolder extends RecyclerView.ViewHolder {
    private ImageView firstImage;

    FirstImageViewHolder(@NonNull View itemView) {
        super(itemView);
        firstImage = itemView.findViewById(R.id.image_home_firstImage);
    }

    void setFirstImageData(FirstImageModel firstImageModel) {
        Glide.with(itemView.getContext())
                .load(firstImageModel.getFirstImageUrl())
                .into(firstImage);
    }
}

/* Live Adapter */
static class LiveViewHolder extends RecyclerView.ViewHolder {
    private ImageView liveImage;

    LiveViewHolder(@NonNull View itemView) {
        super(itemView);
        liveImage = itemView.findViewById(R.id.image_home_liveImage);
    }

    void setLiveImageData(LiveModel liveModel) {
        Glide.with(itemView.getContext())
                .load(liveModel.getImageLiveInfoUrl())
                .into(liveImage);
    }
}

/* DailyImage Adapter */
static class DailyImageViewHolder extends RecyclerView.ViewHolder {
    private ImageView dailyImage;

    DailyImageViewHolder(@NonNull View itemView) {
        super(itemView);
        dailyImage = itemView.findViewById(R.id.image_home_dailyImage);
    }

    void setDailyImageData(DailyImageModel dailyImageModel) {
        Glide.with(itemView.getContext())
                .load(dailyImageModel.getDailyImageUrl())
                .into(dailyImage);
    }
}

我的问题:

当我使用 Retrofit 加载数据时,我不知道如何使用 ViewModel 将 3 种视图类型的数据传递给 RecyclerView。我的 ViewModel 类

public class HomeViewModel extends ViewModel {

private MutableLiveData<List<ItemModel>> homeObjectsList;

private Call<List<ItemModel>> call;

public HomeViewModel(){
    homeObjectsList = new MutableLiveData<>();
}

public MutableLiveData<List<ItemModel>> getHomeItemsListObserver() {
    return homeObjectsList;
}

public void makeApiCallHome() {
    APIServiceHome apiServiceHome = RetroInstanceHome.getRetroClientHome().create(APIServiceHome.class);
    call = apiServiceHome.getHomeObjectsList();
    call.enqueue(new Callback<List<ItemModel>>() {
        @Override
        public void onResponse(Call<List<ItemModel>> call, Response<List<ItemModel>> response) {
            homeObjectsList.postValue(response.body());
        }

        @Override
        public void onFailure(Call<List<ItemModel>> call, Throwable t) {
            homeObjectsList.postValue(null);
        }
    });
}

这也是我应该在 RecyclerView 中显示数据的片段。

public class HomeFragment extends Fragment {

View rootView;
RecyclerView recyclerView;
private List<ItemModel> itemModelList;
private HomeViewModel viewModel;
private HomeAdapter adapter;

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
    rootView = inflater.inflate(R.layout.fragment_home, container, false);

    initializeContent();
    initializeViewModel();
    return rootView;
}

private void initializeContent() {
    recyclerView = rootView.findViewById(R.id.recyclerView_home);
    recyclerView.setAdapter(new HomeAdapter(itemModelList));
}

private void initializeViewModel() {
    ProgressBar progressBar = rootView.findViewById(R.id.progress_bar_home);
    viewModel = ViewModelProviders.of(this).get(HomeViewModel.class);
    viewModel.getHomeItemsListObserver().observe(getActivity(), new Observer<List<ItemModel>>() {
        @Override
        public void onChanged(List<ItemModel> itemModels) {
            if(itemModels != null) {
                progressBar.setVisibility(View.GONE);
                itemModelList = itemModels;
                adapter.setHomeList(itemModels);
            }
        }
    });
    viewModel.makeApiCallHome();
}

我希望这个解释清楚地表明了问题所在。等待你的答复


标签: javaandroidandroid-recyclerview

解决方案


推荐阅读