java - FragmentPagerAdapter 中的 RecyclerView 泄漏

标签 java android memory-leaks leakcanary

我发现在定义的串联情况下,RecyclerView 会导致内存泄漏。为了存档这种效果,我创建了 FragmentPagerAdapter,其中包含以 RecyclerView 为子级的 fragment 。 如果应用程序进入后台或完成,泄漏金丝雀会触发内存泄漏警报。这是我的 Activity 课

public class MainActivity extends AppCompatActivity {

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
    setSupportActionBar(toolbar);

    ViewPager mViewPager = (ViewPager) findViewById(R.id.view_pager);
    List<Fragment> fragments = new LinkedList<>();
    for (int i = 0; i < 10; i++) {
        fragments.add(CustomFragment.newInstance(i));
    }

    mViewPager.setAdapter(new CustomPagerAdapter(getFragmentManager(), fragments));
    mViewPager.setCurrentItem(0, false);
}

  public class CustomPagerAdapter extends FragmentPagerAdapter {

    private List<Fragment> fragments;

    public CustomPagerAdapter(FragmentManager fragmentManager, List<Fragment> fragments) {
        super(fragmentManager);
        this.fragments = fragments;
    }

    @Override
    public Fragment getItem(int position) {
        return fragments.get(position);
    }

    @Override
    public int getCount() {
        return fragments.size();
    }
  }
}

要获取泄漏,RecyclerView 甚至不需要初始化。如果我在 xml 文件中对其进行注释,则不会触发泄漏

public class CustomFragment extends Fragment {

public static final String POSITION = "position";

public static CustomFragment newInstance(int position) {
    Bundle b = new Bundle();
    b.putInt(POSITION, position);
    CustomFragment fragment = new CustomFragment();
    fragment.setArguments(b);
    return fragment;
}

private int position;
private RecyclerView recyclerView;

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    position = getArguments().getInt(POSITION);
}

@Nullable
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    View v = inflater.inflate(R.layout.fragment_custom, container, false);
    TextView textView = (TextView) v.findViewById(R.id.text);
    textView.setText("Position: "+position);
    recyclerView = (RecyclerView) v.findViewById(R.id.pulse_recyclerview);
    return v;
}

@Override
public void onDestroy() {
    super.onDestroy();
    RefWatcher refWatcher = CustomApplication.getRefWatcher(getActivity());
    refWatcher.watch(this);
  }
}

这是泄漏痕迹。 RecyclerView 版本 23.1.1

In com.example.gabin.sampleapplication:1.0:1.
* LEAK CAN BE IGNORED.
* com.example.gabin.sampleapplication.MainActivity has leaked:
* GC ROOT static android.view.inputmethod.InputMethodManager.sInstance
* references android.view.inputmethod.InputMethodManager.mCurRootView
* references com.android.internal.policy.impl.PhoneWindow$DecorView.mContext
* leaks com.example.gabin.sampleapplication.MainActivity instance
* Retaining: 3,9 КБ.
* Reference Key: 67c5e9f4-464e-40c3-b21d-d802fe64a84b
* Device: LGE google Nexus 4 occam
* Android Version: 5.1.1 API: 22 LeakCanary: 1.4-beta1 02804f3
* Durations: watch=5035ms, gc=190ms, heap dump=5948ms, analysis=46384ms

可能是 Android 的错误? 请给出任何解决泄漏的想法,或者帮助我找出它被 leakcanary 触发的原因。

最佳答案

您的堆栈跟踪至少显示了两件事:

  1. 泄漏 Activity 的不是 RecyclerView。它是 ImputMethodManager。
  2. LEAK CAN BE IGNORED .根据 Leak Canary 文档,这是一个已知的 sdk 问题。但我不认为它真的是 Activity 泄漏。如果您检查内存转储,您将看不到多个 Activity 实例。代码现在看起来很安全。

关于java - FragmentPagerAdapter 中的 RecyclerView 泄漏,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35279307/

相关文章:

java - 在 EAR 中捆绑不同版本的嵌入式 JPA 提供程序

java - "Nested"回收者 View

android - 使用 RecyclerView 将按钮放在屏幕的底部中央

在 FFmpeg 中正确分配和填充帧

iphone - 应用程序是否有可能并且有必要实现零内存泄漏?

java - Eclipse Juno 提示未安装 SWT,但可用软件面板提示已安装

java - 如何定义本地关键 GemFire 区域的持久性?

java - Log4j2 - 当前日期文件追加不起作用

java - 过滤列表

java - Spring for Android 内存问题