我有一项活动,其中我替换充当每个屏幕的片段。
我打开一个片段并向后按(从后台弹出它)然后返回到前一个片段。然后,我按下“启动GC”按钮
然后我转储Java堆并获取以下内容。
似乎片段FMenuForm没有从内存中释放出来,对吧?唯一似乎仍然在内存中的东西是RecyclerView中使用的ViewHolders ......但为什么呢?!
我已在片段的this.my_recycler_view.setAdapter(null)
方法中设置onDestroy()
,但它似乎仍然不想gc它。
修改
以下是Adapter
和ViewHolders
的代码。它们都是FMenuForm
public class FMenuForm extends Fragment{
private RecyclerView list_view;
private AdapterMenuForm mAdapter;
private int mIndexSelected = 0;
//
// PRIVATE IMPLEMENTATION
//
private ListItemClickCallback.OnListItemClickListener<AdapterMenuForm.ListItem> mItemClickCallback =
new ListItemClickCallback.OnListItemClickListener<AdapterMenuForm.ListItem>() {
@Override
public boolean onListItemClicked(View view, AdapterMenuForm.ListItem item, int position) {
//TODO:
}
};
/** Some other method and fields here */
//
// ADAPTERS
//
private class AdapterMenuForm extends RecyclerView.Adapter<RowHolder> {
private final int TYPE_SUBCATEGORY = 0;
private final int TYPE_THEME = 1;
private LayoutInflater mInflater;
private ArrayList<ListItem> mSubcategories;
//
// CONSTRUCTOR
//
public AdapterMenuForm() {
mInflater = LayoutInflater.from(getContext());
}
//
// ADAPTER
//
@Override
public int getItemCount() {
return mSubcategories == null ? 0 : mSubcategories.size();
}
@Override
public int getItemViewType(int position) {
return mSubcategories.get(position).isSubcategory() ? TYPE_SUBCATEGORY : TYPE_THEME;
}
@Override
public RowHolder onCreateViewHolder(ViewGroup viewGroup, int type) {
if (type == TYPE_SUBCATEGORY) {
return new RowHolderSubcategory(mInflater.inflate(R.layout.list_item_form_menu_parent, viewGroup, false));
} else {
return new RowHolderTheme(mInflater.inflate(R.layout.list_item_form_menu_child, viewGroup, false));
}
}
@Override
public void onBindViewHolder(final RowHolder holder, int position) {
ListItem data = mSubcategories.get(position);
//Label
holder.text.setText(
data.isSubcategory()
? data.item.subcategory.name
: data.item.theme.name);
//Highlight
holder.itemView.setActivated(mIndexSelected == position);
//Check icon
//TODO:
holder.icon.setActivated(position % 2 == 0);
//Arrow
holder.arrow.setVisibility(
data.children.size() == 0 ? View.INVISIBLE : View.VISIBLE
);
holder.arrow.setImageResource(
data.isExpanded ? R.drawable.selector_expandable_icon_up : R.drawable.selector_expandable_icon_down
);
//Click listeners
holder.itemView.setOnClickListener(new ListItemClickCallback<ListItem>(mItemClickCallback, data, position));
holder.arrow.setOnClickListener(new ListItemClickCallback<ListItem>(mArrowClickCallback, data, position));
}
//
// PUBLIC IMPLEMENTATION
//
public void setData(final FormOptionsListItem items) {
/** Long method. Nothing interesting. Populated mSubcategories*/
}
//
// CLASSES
//
private class ListItem {
boolean isExpanded = false;
FormOptionItem item;
ArrayList<ListItem> children = new ArrayList<>();
public ListItem(FormOptionItem item) {
this.item = item;
}
public boolean isSubcategory() {
return item.remote_theme_id.contentEquals("0");
}
public boolean isTheme() {
return !item.remote_theme_id.contentEquals("0");
}
}
}
public static class RowHolder extends RecyclerView.ViewHolder {
private TextView text;
private View icon;
private ImageView arrow;
public RowHolder(View view) {
super(view);
this.text = (TextView) view.findViewById(R.id.list_item_form_menu_text);
this.icon = view.findViewById(R.id.list_item_form_check_icon);
this.arrow = (ImageView) view.findViewById(R.id.list_item_form_check_icon_arrow);
}
}
public static class RowHolderSubcategory extends RowHolder {
public RowHolderSubcategory(View view) {
super(view);
}
}
public static class RowHolderTheme extends RowHolder {
public RowHolderTheme(View view) {
super(view);
}
}
}
答案 0 :(得分:0)
问题是你在一个类中定义了AdapterMenuForm
,但它不是静态的。请遵循EffectiveJava
中的文档,这不合法。(item22
)
如果声明一个不需要访问封闭实例的成员类,则始终将static修饰符放在其声明中,使其成为静态成员类而非非静态成员类。如果省略此修饰符,则每个实例将对其封闭实例具有无关的引用。存储此引用会花费时间和空间,并且可能导致封闭实例被保留,否则它将有资格进行垃圾回收(第6项)。如果您需要在没有封闭实例的情况下分配实例,则您将无法执行此操作,因为非静态成员类实例需要具有封闭实例。
解决方案是,尝试使您的Adapter
类成为嵌套的静态类或将其移动到另一个文件夹:adapters
?然后创建constructor
以初始化您的mSubCategories
。