使用Otto进行内存泄漏的Leakcanary报告

继续我的上一个问题 ,这是我无法摆脱的第二次内存泄漏..

我读到我需要根据Activity和Fragment生命周期注册和取消注册我的静态Otto总线,所以我添加了注册并取消注册到onStop和onStart的调用…有一个触发事件然后由某些片段接收的按钮在Viewpager内部给我以下内存泄漏:

D/LeakCanary﹕ In com.doesnthaveadomain.leo.calendartracker:1.0:1. D/LeakCanary﹕ * com.doesnthaveadomain.leo.calendartracker.MyFragment has leaked: D/LeakCanary﹕ * GC ROOT static com.doesnthaveadomain.leo.calendartracker.MyBus.BUS D/LeakCanary﹕ * references com.squareup.otto.Bus.handlersByType D/LeakCanary﹕ * references java.util.concurrent.ConcurrentHashMap.table D/LeakCanary﹕ * references array java.util.concurrent.ConcurrentHashMap$Node[].[3] D/LeakCanary﹕ * references java.util.concurrent.ConcurrentHashMap$Node.val D/LeakCanary﹕ * references java.util.concurrent.CopyOnWriteArraySet.al D/LeakCanary﹕ * references java.util.concurrent.CopyOnWriteArrayList.elements D/LeakCanary﹕ * references array java.lang.Object[].[0] D/LeakCanary﹕ * references com.squareup.otto.EventHandler.target D/LeakCanary﹕ * leaks com.doesnthaveadomain.leo.calendartracker.MyFragment instance 

我的代码..

主要活动

 import android.os.Bundle; import android.support.v4.app.Fragment; import android.support.v4.app.FragmentManager; import android.support.v4.app.FragmentStatePagerAdapter; import android.support.v4.view.ViewPager; import android.support.v7.app.AppCompatActivity; import android.view.View; import android.widget.Button; import java.lang.ref.WeakReference; public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); ViewPager mViewPager = (ViewPager) findViewById(R.id.viewpager); MyAdapter myAdapter = new MyAdapter(getSupportFragmentManager(), this); mViewPager.setAdapter(myAdapter); mViewPager.setCurrentItem(5); Button button = (Button) findViewById(R.id.do_something); button.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { MyBus.getInstance().post(new SomeEvent("Something")); } }); } static class SomeEvent { String mString; SomeEvent(String string) { mString = string; } public String getString() { return mString; } } } class MyAdapter extends FragmentStatePagerAdapter { private int mNumberOfViews; private final WeakReference mActivityWeakRef; public MyAdapter(FragmentManager fm, AppCompatActivity activity) { super(fm); mActivityWeakRef = new WeakReference(activity); mNumberOfViews = 10; } @Override public Fragment getItem(int position) { MyFragment myFragment = new MyFragment(); AppCompatActivity activity = mActivityWeakRef.get(); if (activity != null) { MyApp.getRefWatcher(mActivityWeakRef.get()).watch(myFragment); } return myFragment; } @Override public int getCount() { return mNumberOfViews; } } 

MyFragment

 import android.os.Bundle; import android.support.v4.app.Fragment; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import com.squareup.otto.Subscribe; /** * A placeholder fragment containing a simple view. */ public class MyFragment extends Fragment { @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { return inflater.inflate(R.layout.fragment_test, container, false); } @Override public void onStart() { super.onStart(); MyBus.getInstance().register(this); } @Override public void onStop() { super.onStop(); MyBus.getInstance().unregister(this); } @Subscribe public void onEvent(MainActivity.SomeEvent event) { } } 

布局,以防万一.. MainActivity:

      

分段:

   

您正在使用在错误的时间观看参考。 当你绝对确定垃圾收集时,你应该只调用watch(thing) 。 对于您的活动和片段,您将需要以下内容:

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

这是来自LeakCanary FAQ “如何使用它?” 部分