2016-02-05 128 views
0

我一直被困在我的应用程序的内存泄漏问题两天,我在互联网上搜索解决方案,并遇到一个名为LeakCanary的库。添加必要的依赖关系后,我再次启动了应用程序。我正在尝试通过旋转手机来检测泄漏,并在几次轮换后应用程序显示日志。但问题是我不知道如何解释日志。LeakCanary如何解释日志

这里是leakCanary显示日志:

02-05 13:45:14.721 4258-4716/com.carlos.capstone D/LeakCanary: In com.carlos.capstone:1.0:1. 
02-05 13:45:14.721 4258-4716/com.carlos.capstone D/LeakCanary: * com.carlos.capstone.MainActivity has leaked: 
02-05 13:45:14.721 4258-4716/com.carlos.capstone D/LeakCanary: * GC ROOT static android.support.v4.content.LocalBroadcastManager.mInstance 
02-05 13:45:14.721 4258-4716/com.carlos.capstone D/LeakCanary: * references android.support.v4.content.LocalBroadcastManager.mReceivers 
02-05 13:45:14.721 4258-4716/com.carlos.capstone D/LeakCanary: * references java.util.HashMap.table 
02-05 13:45:14.721 4258-4716/com.carlos.capstone D/LeakCanary: * references array java.util.HashMap$HashMapEntry[].[1] 
02-05 13:45:14.721 4258-4716/com.carlos.capstone D/LeakCanary: * references java.util.HashMap$HashMapEntry.key 
02-05 13:45:14.721 4258-4716/com.carlos.capstone D/LeakCanary: * references com.carlos.capstone.FragmentMain$1.this$0 (anonymous class extends android.content.BroadcastReceiver) 
02-05 13:45:14.721 4258-4716/com.carlos.capstone D/LeakCanary: * references com.carlos.capstone.FragmentMain.mViewPager 
02-05 13:45:14.721 4258-4716/com.carlos.capstone D/LeakCanary: * references android.support.v4.view.ViewPager.mAdapter 
02-05 13:45:14.721 4258-4716/com.carlos.capstone D/LeakCanary: * references com.carlos.capstone.FragmentMain$Adapter.mCurrentPrimaryItem 
02-05 13:45:14.721 4258-4716/com.carlos.capstone D/LeakCanary: * references com.carlos.capstone.FragmentAmerica.mAdapterIndexes 
02-05 13:45:14.721 4258-4716/com.carlos.capstone D/LeakCanary: * references com.carlos.capstone.adapters.IndexesAdapter.mCursor 
02-05 13:45:14.721 4258-4716/com.carlos.capstone D/LeakCanary: * references android.content.ContentResolver$CursorWrapperInner.mCursor 
02-05 13:45:14.721 4258-4716/com.carlos.capstone D/LeakCanary: * references android.database.sqlite.SQLiteCursor.mDataSetObservable 
02-05 13:45:14.721 4258-4716/com.carlos.capstone D/LeakCanary: * references android.database.DataSetObservable.mObservers 
02-05 13:45:14.721 4258-4716/com.carlos.capstone D/LeakCanary: * references java.util.ArrayList.array 
02-05 13:45:14.721 4258-4716/com.carlos.capstone D/LeakCanary: * references array java.lang.Object[].[0] 
02-05 13:45:14.721 4258-4716/com.carlos.capstone D/LeakCanary: * references android.widget.CursorAdapter$MyDataSetObserver.this$0 
02-05 13:45:14.721 4258-4716/com.carlos.capstone D/LeakCanary: * references com.carlos.capstone.adapters.IndexesAdapter.mContext 
02-05 13:45:14.721 4258-4716/com.carlos.capstone D/LeakCanary: * leaks com.carlos.capstone.MainActivity instance 
02-05 13:45:14.721 4258-4716/com.carlos.capstone D/LeakCanary: * Reference Key: 4483f896-bc1c-40a1-9bd6-a96ab0d792a0 
02-05 13:45:14.721 4258-4716/com.carlos.capstone D/LeakCanary: * Device: Genymotion generic Google Nexus 5 - 5.1.0 - API 22 - 1080x1920 vbox86p 
02-05 13:45:14.721 4258-4716/com.carlos.capstone D/LeakCanary: * Android Version: 5.1 API: 22 LeakCanary: 1.3.1 
02-05 13:45:14.721 4258-4716/com.carlos.capstone D/LeakCanary: * Durations: watch=6790ms, gc=116ms, heap dump=1357ms, analysis=4544ms 
02-05 13:45:14.721 4258-4716/com.carlos.capstone D/LeakCanary: * Details: 
02-05 13:45:14.721 4258-4716/com.carlos.capstone D/LeakCanary: * Class android.support.v4.content.LocalBroadcastManager 
02-05 13:45:14.721 4258-4716/com.carlos.capstone D/LeakCanary: | static $staticOverhead = byte[] [id=0x12d08781;length=40;size=56] 
02-05 13:45:14.721 4258-4716/com.carlos.capstone D/LeakCanary: | static 

... 

与FragmentAmerica片段修订

package com.carlos.capstone; 

import android.app.Activity; 
import android.content.Intent; 
import android.database.Cursor; 
import android.net.Uri; 
import android.os.Bundle; 
import android.support.annotation.Nullable; 
import android.support.customtabs.CustomTabsIntent; 
import android.support.v4.app.Fragment; 
import android.support.v4.app.LoaderManager; 
import android.support.v4.content.ContextCompat; 
import android.support.v4.content.CursorLoader; 
import android.support.v4.content.Loader; 
import android.util.Log; 
import android.view.LayoutInflater; 
import android.view.View; 
import android.view.ViewGroup; 
import android.view.ViewTreeObserver; 
import android.widget.ScrollView; 
import android.widget.TextView; 
import android.widget.Toast; 

import com.carlos.capstone.adapters.IndexesAdapter; 
import com.carlos.capstone.adapters.RssNewsAdapter; 
import com.carlos.capstone.customtabs.CustomTabActivityHelper; 
import com.carlos.capstone.database.CapstoneContract; 
import com.linearlistview.LinearListView; 


/** 
* Created by Carlos on 19/01/2016. 
*/ 
public class FragmentAmerica extends Fragment implements LoaderManager.LoaderCallbacks<Cursor> { 
    private LinearListView mVerticalListView; 
    private LinearListView mIndexesListView; 
    private ScrollView mScrollView; 
    private boolean mRotationDone=false; 
    private static final String KEY_POSX="x_pos"; 
    private static final String KEY_POSY="y_pos"; 
    private static final int NEWS_LOADER=0; 
    private static final int INDEXES_LOADER=1; 
    private RssNewsAdapter mAdapter; 
    private IndexesAdapter mAdapterIndexes; 
    private static final String selectionNews =CapstoneContract.NewsEntity.REGION + " =?"; 
    private static final String[] selectionArgsNews =new String[]{"AMERICA"}; 
    private static final String selectionIndexes=CapstoneContract.IndexesEntity.REGION + " =?"; 
    private static final String[] selectionArgsIndexes=new String[]{"AMERICA"}; 
    private static final String sortByDateDesc = CapstoneContract.NewsEntity.DATE + " DESC"; 
    private int x; 
    private int y; 

    LinearListView.OnItemClickListener mListener = new LinearListView.OnItemClickListener() { 


     @Override 
     public void onItemClick(LinearListView parent, View view, int position,long id) { 
      final TextView tvLink,tvTitle; 
      tvLink= (TextView) view.findViewById(R.id.txtUrlLink); 
      tvTitle= (TextView) view.findViewById(R.id.txtTitulo); 


      Uri uri=null; 
      uri = Uri.parse(tvLink.getText().toString()); 

      //customization possibilities 
      CustomTabsIntent customTabsIntent = new CustomTabsIntent.Builder() 
        .setToolbarColor(ContextCompat.getColor(getActivity(),R.color.colorPrimary)) 
        .setShowTitle(true) 
        .build(); 

      CustomTabActivityHelper.openCustomTab(getActivity(), customTabsIntent,uri, 
        //in case the user doen't have chromium v 45 installed, offer an alternative 
        //browser experience with WebView 
        new CustomTabActivityHelper.CustomTabFallback() { 
         @Override 
         public void openUri(Activity activity, Uri uri) { 
          Intent intent=new Intent(getActivity(),DetailsNewsActivity.class); 
          intent.putExtra("url",tvLink.getText()); 
          intent.putExtra("title",tvTitle.getText()); 
          startActivity(intent); 
         } 
        }); 

     } 
    }; 
     @Nullable 
    @Override 
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { 
     View view=inflater.inflate(R.layout.fragment_america,container,false); 
     mVerticalListView = (LinearListView) view.findViewById(R.id.verticalList); 
     mIndexesListView= (LinearListView) view.findViewById(R.id.indexesListAmerica); 


     mScrollView= (ScrollView) view.findViewById(R.id.scrollViewAm); 



     mScrollView.getViewTreeObserver().addOnScrollChangedListener(new ViewTreeObserver.OnScrollChangedListener() { 
      @Override 
      public void onScrollChanged() { 
       x=mScrollView.getScrollX(); 
       Log.d("VILLANUEVA","x pos:"+mScrollView.getScrollX()+",y pos:"+mScrollView.getScrollY()); 
       y=mScrollView.getScrollY(); 
      } 
     }); 


     mAdapter =new RssNewsAdapter(getActivity().getApplicationContext(),null,NEWS_LOADER); 
     mAdapterIndexes=new IndexesAdapter(getActivity().getApplicationContext(),null,INDEXES_LOADER); 

     //set both adapters 
     mIndexesListView.setAdapter(mAdapterIndexes); 
     mVerticalListView.setAdapter(mAdapter); 

     mVerticalListView.setOnItemClickListener(mListener); 
     getLoaderManager().initLoader(NEWS_LOADER,null,this); 
     getLoaderManager().initLoader(INDEXES_LOADER,null,this); 

     if(savedInstanceState==null) { 

     } else { 
      mRotationDone=true; 
      //scroll to saved position 
      mScrollView.scrollTo(savedInstanceState.getInt(KEY_POSX),savedInstanceState.getInt(KEY_POSY)); 

     } 
     Toast.makeText(getActivity(),"onCreateViewAmerica",Toast.LENGTH_SHORT).show(); 
     return view; 
    } 

    @Override 
    public void onResume() { 
     super.onResume(); 

     Toast.makeText(getActivity(),"onResumeAmerica",Toast.LENGTH_SHORT).show(); 
    } 



    @Override 
    public void onSaveInstanceState(Bundle outState) { 
     super.onSaveInstanceState(outState); 

     outState.putInt(KEY_POSX,mScrollView.getScrollX()); 
     outState.putInt(KEY_POSY,mScrollView.getScrollY()); 

    } 



    @Override 
    public Loader<Cursor> onCreateLoader(int id, Bundle args) { 
     if (id==NEWS_LOADER) { 
      return new CursorLoader(getActivity().getApplicationContext(), 
        CapstoneContract.NewsEntity.CONTENT_URI, null, selectionNews, selectionArgsNews, sortByDateDesc); 
     } else if(id==INDEXES_LOADER) { 
      return new CursorLoader(getActivity().getApplicationContext(), 
        CapstoneContract.IndexesEntity.CONTENT_URI,null,selectionIndexes,selectionArgsIndexes,null); 
     } 
     return null; 

    } 

    @Override 
    public void onLoadFinished(Loader<Cursor> loader, Cursor data) { 

     switch(loader.getId()) { 
      case NEWS_LOADER: 

       mAdapter.swapCursor(data); 

       break; 
      case INDEXES_LOADER: 
       mAdapterIndexes.swapCursor(data); 
       break; 

     } 
     mScrollView.postDelayed(new Runnable() { 
      @Override 
      public void run() { 
       mScrollView.scrollTo(x,y); 
      } 
     },200); 

     Log.d("VILLANUEVA","move to x pos:"+x+",y pos:"+y); 


    } 

    @Override 
    public void onLoaderReset(Loader<Cursor> loader) { 

     switch(loader.getId()) { 
      case NEWS_LOADER: 
       mAdapter.swapCursor(null); 
       break; 
      case INDEXES_LOADER: 
       mAdapterIndexes.swapCursor(null); 
       break; 

     } 

    } 

    @Override 
    public void onDestroy() { 
     super.onDestroy(); 
//  ExampleApplication application = (ExampleApplication) getActivity().getApplicationContext(); 
//  application.mustDie(this); 
    } 
} 

我敢肯定,也是问题与IndexAdapter,如果我注释掉以下行编码问题消失;

getLoaderManager().initLoader(INDEXES_LOADER,null,this); 

return new CursorLoader(getActivity().getApplicationContext(), 
        CapstoneContract.IndexesEntity.CONTENT_URI,null,selectionIndexes,selectionArgsIndexes,null); 
+0

我的内存泄漏消失了。请参阅下面的链接解决方案:http://stackoverflow.com/questions/35244301/a-line-of-code-is-causing-memory-leaks-in-my-app/35265828#35265828 –

回答

0

当您创建IndexesAdapter,而不是在构造函数传递this,使用this.getApplicationContext()

+0

谢谢你的回答,我用this.getApplicationContext()测试了它,但问题仍然存在。看到我更新的问题。 –