Recently I have created RecyclerView with Multiple ViewTypes followed this video. In the video the lecturer followed the traditional method of sending data using ArrayList In MainAvtivity. But when I used ViewModel and Retrofit it is not passing any data and nothing show in the screen.
And here an expiation of what I have done.
First:
I have 3 diffrents types of views so I created a 3 model classes for each view called (FirstImageModel,LiveModel,DailyImageModel).
FirstImageModel class -- All other 2 classes have same stretcher.
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;
}
and I have created a fourth class called ItemModel that have type int and Object 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;
}
}
Second:
I have created Adapter class called HomeAdapter that extends from RecyclerView and I made 3 classes for eatch view inside the same class HomeAdapter.
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);
}
}
My Problem:
When I use Retrofit to load the data, I don't Know how to pass the 3 views types data to the RecyclerView using ViewModel. My ViewModel class.
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);
}
});
}
Also here's my fragment that should dislay the data in 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();
}
I hope this explanation was clear to show the problem. Waiting for your answer