2016-08-09 15 views
2

我是新来的Android(刚刚完成我的第一类)和我有内存泄漏问题是我不知道是一个真正的问题还是没有挣扎。我已经采取了示例代码读取联系人数据库,可以通过“下载示例”按钮在Android开发者网站这里下载:Android的内存泄漏,我可以肯定,如果我真的有一个

https://developer.android.com/training/contacts-provider/retrieve-details.html

的应用程序运行在自己的(API 22或罚款更少由于READ_CONTACTS权限更改)。我想在自己的应用程序中使用示例中的主要活动作为主要活动的子项,以选择联系人并传回其URI以用于存储一些自定义联系信息。我使用startActivityForResult()绑定到菜单图标来启动活动,作为我主要活动的一个子项。我已经改变中的示例代码非常少除了在示例应用程序点击一个联系人时,执行结束(),而不是启动的详细活动:

原文:

@Override 
public void onContactSelected(Uri contactUri) { 
    if (isTwoPaneLayout && mContactDetailFragment != null) { 
     // If two pane layout then update the detail fragment to show the selected contact 
     mContactDetailFragment.setContact(contactUri); 
    } else { 
     // Otherwise single pane layout, start a new ContactDetailActivity with 
     // the contact Uri 
     Intent intent = new Intent(this, ContactDetailActivity.class); 
     intent.setData(contactUri); 
     startActivity(intent); 
    } 
} 

新:

@Override 
public void onContactSelected(Uri contactUri) { 

    Intent intent = new Intent(); 
    intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); 

    intent.setData(contactUri); 
    Log.d(LOG_TAG, contactUri.toString()); 
    setResult(RESULT_OK, intent); 
    finish(); 
} 

的UI功能工作正常,我也得到了URI的回调预期。但是,StrictMode已启用,并且每次调用它时都会报告有一个新的子活动实例。即使有多个方向更改,原始应用也不会发生这种情况。我尝试了很多事情来消除我的新应用程序中的这个问题无济于事。以下是我试过到目前为止:

我尝试设置的意图标志FLAG_ACTIVITY_REORDER_TO_FRONT和FLAG_ACTIVITY_CLEAR_TOP。

我尝试新呼叫到活动之前强制垃圾回收:

  if (BuildConfig.DEBUG) 
      { 
       System.gc(); 
      } 

      startActivityForResult(intent, 1); 

我删除从XML布局片段定义,并通过FragmentManager替代任何现有的实例:

 if (getSupportFragmentManager().findFragmentByTag(ADDCONTACTSFRAGMENT_TAG) == null) { 
      getSupportFragmentManager().beginTransaction() 
        .replace(R.id.add_contacts_container, new AddContactsFragment(), ADDCONTACTSFRAGMENT_TAG) 
        .commit(); 
     } 

我读了不重新初始化为null任何听众可能会导致泄漏,所以我试图创建一个成员变量所有这些,在儿童活动片段的onDestroyView和方法的onDestroy重置他们:

@Override 公共无效的onDestroy(){ super.onDestroy();

if (mCursor != null) { 
     mCursor.close(); 
     mCursor = null; 
    } 

    mAdapter.swapCursor(null); 
    mAdapter = null; 

    mLoader = null; 

    mContext = null; 

    Log.d(LOG_TAG, "In onDestroy()"); 
} 

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

    getListView().setOnItemClickListener(null); 
    getListView().setOnScrollListener(null); 

    mSearchView.setOnQueryTextListener(null); 

    if (Utils.hasICS()) { 
     // This listener added in ICS 
     MenuItemCompat.setOnActionExpandListener(mSearchItem, null); 
    } 
    mSearchTerm = null; 
    mSearchItem = null; 
    mSearchView = null; 

    //setListAdapter(null); 
    mView = null; 

    mOnContactSelectedListener = null; 

    mDialogClickListener = null; 

    mImageLoader.setPauseWork(false); 
    mImageLoader = null; 

    if (mAdapterView != null) { 
     mAdapterView.setOnItemClickListener(null); 
     mClickView.setOnClickListener(null); 
     mClickView = null; 
     mAdapterView = null; 
    } 

    Log.d(LOG_TAG, "In onDestroyView()"); 
} 

我还发现,被说成是有必要删除所有视图对象的unbindDrawables()方法的几个例子,但它并不适用于一个AdapterView,此片段是工作。这可能是问题吗?

我已经在设备监视器中使用了“分配跟踪”选项卡,并通过独立MAT应用程序对堆进行分析,以验证内存中是否存在子片段的多个实例,但我不确定这一点,如果这真的是一个泄漏或垃圾收集只是不会删除片段实例,直到内存受限。任何建议将不胜感激。

回答

0

有一个Android库,可以帮助正确地分析内存泄漏:leakcanary

+0

感谢,@Ozuf,leakcanary是很容易实现。它确认儿童活动正在泄漏。不幸的是它没有提供任何细节,所以我仍然想知道为什么我的版本泄漏,而原始版本没有。我想我会做比较比较,看看我是否介绍了一些东西。 –