1

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

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错误?请告诉我如何修复泄漏,或帮助我找出泄漏金丝雀触发它的原因。

4

1 回答 1

1

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

  1. 泄漏活动的不是 RecyclerView。它是 ImputMethodManager。
  2. 泄漏可以忽略。根据 Leak Canary 文档,这是一个已知的 sdk 问题。但我不认为它真的是活动泄漏。如果您检查内存转储,您将看不到多个活动实例。代码现在看起来很安全。
于 2016-02-09T00:22:26.773 回答