Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Will a passed viewmodel into a recyclerview adapter cause for memory leaks?

Currently i'm experimenting with viewmodels and was wondering if passing a viewmodel to a recyclerview adapter will cause a memory leak? The only purpose of the viewmodel in the adapter is to give a new url of the image to display in the activity

I have no idea if an interface is the better way or is there a better way receive onclick events from a recyclerview?

here is my code:

Viewmodel:

public class WallDetailViewModel extends AndroidViewModel {
private final String apiAddress = "*";
private BlindWall detailWall;
private MutableLiveData<String> mainImageUrl;

public WallDetailViewModel(@NonNull Application application) {
    super(application);
}

public LiveData<String> getMainImageUrl() {
    if(mainImageUrl == null) {
        mainImageUrl = new MutableLiveData<>();
        mainImageUrl.postValue(getImageUrl(0));
    }
    return mainImageUrl;
}

public void setWall(BlindWall wall) {
    detailWall = wall;
}

public String getImageUrl(int position) {
    String returnValue = null;
    if(position >= 0 && position < detailWall.getImagesUrls().size()) {
        returnValue = apiAddress + detailWall.getImagesUrls().get(position);
    }
    return returnValue;
}

public String getWallName() {
    return detailWall.getTitle();
}

public String getDutchDescription() {
    return detailWall.getDescriptionDutch();
}

public String getEnglishDescription() {
    return detailWall.getDescriptionEnglish();
}

public int getImageUrlSize() {
    return detailWall.getImagesUrls().size();
}

public void setMainImage(String url) {
    mainImageUrl.postValue(url);
}

}

Adapter:

public class ImageSliderAdapter extends RecyclerView.Adapter<ImageSliderAdapter.ViewHolder2> {
private WallDetailViewModel viewModel;

public ImageSliderAdapter(WallDetailViewModel viewModel) {
    this.viewModel = viewModel;
}

public static class ViewHolder2 extends RecyclerView.ViewHolder {
    public ImageView WallFrontPaper;

    public ViewHolder2(View itemView) {
        super(itemView);
        WallFrontPaper = itemView.findViewById(R.id.ImageItem);
    }
}

@Override
public ViewHolder2 onCreateViewHolder(ViewGroup parent, int viewType) {
    LayoutInflater inflater = LayoutInflater.from(parent.getContext());
    View v = inflater.inflate(R.layout.imageslider_item, parent, false);

    return new ViewHolder2(v);
}

@Override
public void onBindViewHolder(ViewHolder2 holder, int position) {
    Picasso.with(holder.itemView.getContext()).load(viewModel.getImageUrl(position)).fit().centerCrop().into(holder.WallFrontPaper);
    holder.WallFrontPaper.setOnClickListener(view -> viewModel.setMainImage(viewModel.getImageUrl(position)));
}

@Override
public int getItemCount() {
    return viewModel.getImageUrlSize();
}

}

Thank you,

Ian

like image 904
Tragamota Avatar asked Oct 17 '22 11:10

Tragamota


1 Answers

From the code you posted, I'd say you should be fine. However, having an interface, as you mentioned, could help in making things clearer, as you'd pass that to your adapter instead, without exposing the whole view model.

Looking at this bit .setOnClickListener(view -> viewModel.setMainImage(viewModel.getImageUrl(position))); makes me wonder if you can't just pass let the view model know that an item has been clicked, since you're using the view model again to figure out which image url to pass as an argument, based on the position.

So, if using an interface you'd have something like setOnClickListener(view -> itemClickListener.itemClicked(position). Your view model would implement this interface.

like image 58
takecare Avatar answered Nov 15 '22 05:11

takecare