Answer the question
In order to leave comments, you need to log in
Android. How to deal with such memory leaks?
LeakCanary reports leaks in click handlers:
@Override
protected void setupAdapter(CatalogAdapter adapter) {
adapter.setOnItemClickListener(new BaseAdapter.OnItemClickListener<Item>()
{
@Override
public void onClick(View view, Item item, int position) {
// Утечка, как я понял, происходит из-за getContext(), даже если никаких нажатий не происходит. Возможно я ошибаюсь и проблема где-то в другом месте.
Intent intent = new Intent(getContext(), ShowActivity.class);
intent.putExtra(KEY_ITEM, Parcels.wrap(item));
startActivity(intent);
}
});
}
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container,
@Nullable Bundle savedInstanceState) {
View view = inflater.inflate(getLayoutResource(), container, false);
...
setupAdapter(getAdapter());
...
return view;
}
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setRetainInstance(true);
...
adapter = createAdapter();
...
}
public abstract class BaseAdapter<T, VH extends RecyclerView.ViewHolder> extends PaginationAdapter<T, VH>
{
private List<T> items;
private Context context;
private OnItemClickListener<T> onItemClickListener;
public BaseAdapter(Context ctx) {
items = new ArrayList<>();
context = ctx.getApplicationContext();
}
@Override
public int getItemCount() {
return items.size();
}
public T getItem(int position) {
return items.get(position);
}
public void setOnItemClickListener(OnItemClickListener<T> onItemClickListener) {
this.onItemClickListener = onItemClickListener;
}
protected void callOnClick(View view, T item, int position) {
if (onItemClickListener != null) {
onItemClickListener.onClick(view, item, position);
}
}
protected LayoutInflater getLayoutInflater(View view) {
return LayoutInflater.from(view.getContext());
}
protected Context getContext() {
return context;
}
public interface OnItemClickListener<T>
{
void onClick(View view, T item, int position);
}
}
Answer the question
In order to leave comments, you need to log in
Sergey,
1. Fragments with setRetainInstance(true) set must not have an interface/view at all! This is written in the documentation, in black and white. This is your leak.
additionally: And you can’t put it in the backstack either!
2. any anonymous/internal non-static class - has a non-explicit reference to the external one!
3.
- you don't need to do anything special in the onCreate method of the fragment.
- in the onCreateView method, you need to create a current view, well, or even such small operations as setHasOptionsMenu.
- all the main logic is done in onViewCreated, after the fragment has been attached and created all the views.
4. for the future, you can reset any listener in the
onDestroy - Activity method
onDestroyView - Fragment
for example
adapter.setOnItemClickListener(null)
and it is important to do this BEFORE the super method!
5. From experience, all these LeakCanaries are for lazy hipsters.
A normal tool that will tell you exactly what is flowing, how much, and most importantly, WHO is holding this link will show - MAT (Memory Analyzer Tool) in conjunction with DDMS, do not be too lazy to figure it out, there are a lot of articles on Habré.
Didn't find what you were looking for?
Ask your questionAsk a Question
731 491 924 answers to any question