I am getting a memory leak notification via leak canary where it says my fragment instance leaks due to references held from eventlisteners and Arraylist.array. Not sure how to fix this, any ideas?
@Override
ArrayList<myInterface> getnewList() {
ArrayList<myInterface> inst = new ArrayList<>();
inst.addAll(myRepository.getList());
inst.addAll(myRepository.getOtherList());
Collections.sort(inst, myRepository.myComparator);
return inst;
}
Here's the leak trace which gives an indication of the leak:
In com.myproject.project2.alpha.debug:3.0.0:3000000.
* com.project.newzy.dashboard.myListFragment has leaked:
* GC ROOT static com.myproject.repository.myRepository.eventListeners
* references java.util.ArrayList.array
* references array java.lang.Object[].[0]
* leaks com.project.newzy.dashboard.myListFragment instance
* Retaining: 251 KB.
* Reference Key: cc806908-52f6-42f5-be98-b39665dfa218
* Device: samsung samsung SM-J327P j3popltespr
* Android Version: 6.0.1 API: 23 LeakCanary: 1.5.1 1be44b3
* Durations: watch=5463ms, gc=131ms, heap dump=3776ms, analysis=40370ms
* Details:
* Class com.myproject.repository.myRepository
| static eventListeners = java.util.ArrayList@587750272 (0x23085b80)
| static Comparator = com.myproject.repository.myRepository$5@587741136 (0x230837d0)
| static $staticOverhead = byte[40]@584327169 (0x22d42001)
| static initialized = true
| static lock = java.lang.Object@587741152 (0x230837e0)
| static cache = java.util.concurrent.ConcurrentHashMap@587732480 (0x23081600)
* Instance of java.util.ArrayList
| static $staticOverhead = byte[16]@1893860329 (0x70e203e9)
| static MIN_CAPACITY_INCREMENT = 12
| static serialVersionUID = 8683452581122892189
| array = java.lang.Object[12]@591375616 (0x233fad00)
| size = 1
| modCount = 1
| shadow$_klass_ = java.util.ArrayList
| shadow$_monitor_ = 0
* Array of java.lang.Object[]
| [0] = com.project.newzy.dashboard.myListFragment@596231392 (0x2389c4e0)
| [1] = null
| [2] = null
| [3] = null
| [4] = null
| [5] = null
| [6] = null
| [7] = null
| [8] = null
| [9] = null
| [10] = null
| [11] = null
* Instance of com.project.newzy.dashboard.myListFragment
| static $staticOverhead = byte[16]@583464961 (0x22c6f801)
| static serialVersionUID = 0
| static $change = null
| adapter = com.project.newzy.dashboard.DashboardAdapter@590877408 (0x233812e0)
| myRepository = com.myproject.repository.myRepository@587661072 (0x2306ff10)
| inst = java.util.ArrayList@591400160 (0x23400ce0)
| emptyLayout = android.widget.RelativeLayout@593542144 (0x2360bc00)
| emptyMessage = android.support.v7.widget.AppCompatTextView@593544192 (0x2360c400)
| floatingActionButton = android.support.design.widget.FloatingActionButton@594071552 (0x2368d000)
| roomList = com.project.gui.advancedrecyclerview.AdvancedRecyclerView@593541120 (0x2360b800)
| selectedVGroupID = null
| listAdapter = com.project.newzy.dashboard.DashboardAdapter@590877408 (0x233812e0)
| listDivider = com.project.newzy.base.helpers.DividerItemDecoration@589723120 (0x232675f0)
| listManager = android.support.v7.widget.LinearLayoutManager@591052128 (0x233abd60)
| listView = com.project.gui.advancedrecyclerview.AdvancedRecyclerView@593541120 (0x2360b800)
| mAdded = true
| mAnimationInfo = null
| mArguments = null
| mBackStackNesting = 0
| mCalled = true
| mCheckedForLoaderManager = true
| mChildFragmentManager = android.support.v4.app.FragmentManagerImpl@588818688 (0x2318a900)
| mChildNonConfig = null
| mContainer = android.support.v4.view.ViewPager@597927936 (0x23a3a800)
| mContainerId = 2131755178
| mDeferStart = false
| mDetached = false
| mFragmentId = 2131755178
| mFragmentManager = android.support.v4.app.FragmentManagerImpl@598589728 (0x23adc120)
| mFromLayout = false
| mHasMenu = false
| mHidden = false
| mHiddenChanged = false
| mHost = android.support.v4.app.FragmentActivity$HostCallbacks@598610224 (0x23ae1130)
| mInLayout = false
| mIndex = 1
| mInnerView = android.widget.RelativeLayout@593536000 (0x2360a400)
| mIsNewlyAdded = false
| mLoaderManager = null
| mLoadersStarted = true
| mMenuVisible = true
| mParentFragment = null
| mPostponedAlpha = 0.0
| mRemoving = false
| mRestored = false
| mRetainInstance = false
| mRetaining = false
| mSavedFragmentState = null
| mSavedViewState = null
| mState = 5
| mTag = java.lang.String@590080848 (0x232beb50)
| mTarget = null
| mTargetIndex = -1
| mTargetRequestCode = 0
| mUserVisibleHint = true
| mView = android.widget.RelativeLayout@593536000 (0x2360a400)
| mWho = java.lang.String@591143744 (0x233c2340)
| shadow$_klass_ = com.project.newzy.dashboard.myListFragment
| shadow$_monitor_ = -2032154546
* Excluded Refs:
| Field: android.view.inputmethod.InputMethodManager.mNextServedView
| Field: android.view.inputmethod.InputMethodManager.mServedView
| Field: android.view.inputmethod.InputMethodManager.mServedInputConnection
| Field: android.view.inputmethod.InputMethodManager.mCurRootView
| Field: android.os.UserManager.mContext
| Field: android.net.ConnectivityManager.sInstance
| Field: android.view.Choreographer$FrameDisplayEventReceiver.mMessageQueue (always)
| Thread:FinalizerWatchdogDaemon (always)
| Thread:main (always)
| Thread:LeakCanary-Heap-Dump (always)
| Class:java.lang.ref.WeakReference (always)
| Class:java.lang.ref.SoftReference (always)
| Class:java.lang.ref.PhantomReference (always)
| Class:java.lang.ref.Finalizer (always)
| Class:java.lang.ref.FinalizerReference (always)
Please let me know if you guys have faced this before and have any clues about how to go about fixing it?
The stack trace shows that the com.myproject.repository.myRepository
is holding a reference to com.project.newzy.dashboard.myListFragment
in the eventListeners
array.
I'm not sure exactly what your myRepository
is but (probably it used as an Observable
) it's holding a reference to an myListFragment
(probably a Fragment
) that the UI
needs to destroy.
To solve the issue you need to ensure that when the myListFragment
is about to be destroyed it's no longer part of the eventListeners
array. Just remove the listener from the array in onPause
and register it back in onResume
.