2

I have a RecyclerView in a Fragment. I'm sure Memory Leak came from RecyclerView because when I add RecyclerView, Memory leak appears.

This is my RecyclerView Adapter:

public class TabsAdapter extends RecyclerView.Adapter<TabsAdapter.SetViewHolder> {

private Context context;
private List<TabsModel> items = Collections.emptyList();
private TabsDatabaseHelper databaseHelper;
private Dialog dialog;

public TabsAdapter(Context context, List<TabsModel> items, Dialog dialog) {
    databaseHelper = new TabsDatabaseHelper(context);
    this.context = context;
    this.items = items;
    this.dialog = dialog;
}

@NonNull
@Override
public TabsAdapter.SetViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
    View view = LayoutInflater.from(parent.getContext())
            .inflate(R.layout.item_tabs, parent, false);
    return new SetViewHolder(view);
}

@Override
public void onBindViewHolder(@NonNull TabsAdapter.SetViewHolder holder, final int position) {
    //I clean here codes, By removing the code here, Memory Leak again occur
}

@Override
public int getItemCount() {
    return items == null ? 0 : items.size();
}

static class SetViewHolder extends RecyclerView.ViewHolder {

    private ImageView ivShot, ivRemove;
    private TextView tvTitle, tvUrl;
    private ConstraintLayout constraintLayout;

    private SetViewHolder(@NonNull View itemView) {
        super(itemView);
        ivShot = itemView.findViewById(R.id.iv_item_tabs);
        ivRemove = itemView.findViewById(R.id.iv_clear_item_tabs);
        tvTitle = itemView.findViewById(R.id.tv_title_item_tabs);
        tvUrl = itemView.findViewById(R.id.tv_url_item_tabs);
        constraintLayout = itemView.findViewById(R.id.const_item_tabs);
    }
}
}

And in Fragment:

    tabsModelArrayList.clear();
    tabsModelArrayList = tabsDatabaseHelper.getData();
    tabsAdapter = new TabsAdapter(context, tabsModelArrayList, getDialog());
    recyClerView.setHasFixedSize(true);
    LinearLayoutManager linearLayoutManager = new LinearLayoutManager(context);
    recyClerView.setLayoutManager(linearLayoutManager);
    recyClerView.setAdapter(tabsAdapter);

So the Memory Leak is :

leakcanary library

I try to set null view in adapter:

@Override
public void onViewDetachedFromWindow(@NonNull SetViewHolder holder) {
    super.onViewDetachedFromWindow(holder);
    holder.constraintLayout = null;
    holder.ivRemove = null;
    holder.ivShot = null;
    holder.tvTitle = null;
    holder.tvUrl = null;
}

Or in inDesroy Fragment, I set:

recyClerView.setAdapter(null);

But I have still that error. Can you help me?

----------Edit

I remove Context and DatabaseHelper from Adapter:

public class TabsAdapter extends RecyclerView.Adapter<TabsAdapter.SetViewHolder> {

private List<TabsModel> items = Collections.emptyList();
private Dialog dialog;

public TabsAdapter(List<TabsModel> items, Dialog dialog) {
    this.items = items;
    this.dialog = dialog;
}

@NonNull
@Override
public TabsAdapter.SetViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
    View view = LayoutInflater.from(parent.getContext())
            .inflate(R.layout.item_tabs, parent, false);
    return new SetViewHolder(view);
}

@Override
public void onBindViewHolder(@NonNull TabsAdapter.SetViewHolder holder, final int position) {
    //I clean here codes, By removing the code here, Memory Leak again occur
}

@Override
public int getItemCount() {
    return items == null ? 0 : items.size();
}

static class SetViewHolder extends RecyclerView.ViewHolder {

    private ImageView ivShot, ivRemove;
    private TextView tvTitle, tvUrl;
    private ConstraintLayout constraintLayout;

    private SetViewHolder(@NonNull View itemView) {
        super(itemView);
        ivShot = itemView.findViewById(R.id.iv_item_tabs);
        ivRemove = itemView.findViewById(R.id.iv_clear_item_tabs);
        tvTitle = itemView.findViewById(R.id.tv_title_item_tabs);
        tvUrl = itemView.findViewById(R.id.tv_url_item_tabs);
        constraintLayout = itemView.findViewById(R.id.const_item_tabs);
    }
}

@Override
public void onViewDetachedFromWindow(@NonNull SetViewHolder holder) {
    super.onViewDetachedFromWindow(holder);
    holder.constraintLayout = null;
    holder.ivRemove = null;
    holder.ivShot = null;
    holder.tvTitle = null;
    holder.tvUrl = null;
}
}

But not fix the memory leak.

Marlen Schreiner
  • 726
  • 10
  • 25

1 Answers1

0

I can suggest you two things. Firstly you must not send Context in your recyclerView adapter constructor. In your code you used it in OnCreateView as parent.getContext anyway. Sending context in your constructor causes memory leaks. Secondly, I think you should not initialize DatabaseHelper in your constructor. You can do it before creating your adapter instance.Get your list from your database and send your list instead of DatabaseHelper in your constructor.