2015-09-23 3 views
4

Вслед за my last question, вот вторая утечка памяти я не могу избавиться от ..Leakcanary отчет утечки памяти с помощью Отто

Я читал, что мне нужно зарегистрировать и отменить мой статический автобус Отто по деятельности и фрагмент жизненного цикл, поэтому я добавил регистрацию и отмену регистрации вызовов на 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 

Мой код ..

MainActivity

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<AppCompatActivity> mActivityWeakRef; 

    public MyAdapter(FragmentManager fm, 
        AppCompatActivity activity) { 
     super(fm); 

     mActivityWeakRef = new WeakReference<AppCompatActivity>(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:

<LinearLayout 
    android:layout_width="match_parent" 
    android:layout_height="match_parent" 
    android:orientation="vertical" 
    xmlns:android="http://schemas.android.com/apk/res/android"> 

    <android.support.design.widget.AppBarLayout 
     xmlns:app="http://schemas.android.com/apk/res-auto" 
     xmlns:android="http://schemas.android.com/apk/res/android" 
     android:id="@+id/toolbar_appbar_layout" 
     android:layout_width="match_parent" 
     android:layout_height="wrap_content" 
     android:fitsSystemWindows="true" > 

     <android.support.v7.widget.Toolbar 
      android:id="@+id/toolbar" 
      android:layout_width="match_parent" 
      android:layout_height="?attr/actionBarSize" 
      android:background="?attr/colorPrimary" 
      app:layout_scrollFlags="scroll|enterAlways" 
      app:theme="@style/AppTheme.Toolbar" 
      app:popupTheme="@style/AppTheme.Toolbar.Popup"> 

     </android.support.v7.widget.Toolbar> 

    </android.support.design.widget.AppBarLayout> 

    <Button 
     android:id="@+id/do_something" 
     android:layout_width="wrap_content" 
     android:layout_height="wrap_content" 
     android:text="DO"/> 

    <android.support.v4.view.ViewPager 
     android:id="@+id/viewpager" 
     android:layout_width="match_parent" 
     android:layout_height="match_parent" /> 

</LinearLayout> 

Фрагмент:

<LinearLayout 
    android:layout_width="match_parent" 
    android:layout_height="match_parent" 
    android:orientation="vertical" 
    android:paddingLeft="@dimen/activity_vertical_margin" 
    android:paddingStart="@dimen/activity_vertical_margin" 
    android:paddingRight="@dimen/activity_vertical_margin" 
    android:paddingEnd="@dimen/activity_vertical_margin" 
    xmlns:app="http://schemas.android.com/apk/res-auto" 
    xmlns:android="http://schemas.android.com/apk/res/android"> 

</LinearLayout> 

ответ

7

Вы используете просмотр ссылки в неподходящее время. Нужно только позвонить watch(thing), когда вы абсолютно уверены, что thing будет собираться мусором. Для вашей деятельности и фрагментов, вы хотите что-то вроде этого:

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

То есть из LeakCanary FAQ "How do I use it?" section

+0

Спасибо много, что, кажется, решить эту проблему! Я должен, конечно же, заняться этим медленнее, изучая библиотеки, если я не буду уделять больше времени, чтобы читать внимательно. Я предположил, что рефлектор работает так же, как и для своих действий. – sickmartian

+0

Новая ссылка [Как это использовать?] (Https://github.com/square/leakcanary/wiki/FAQ#how-do-i-use-it) –

Смежные вопросы