Last active
August 18, 2021 07:31
-
-
Save Haoxiqiang/980a09aed98f410f3a7aca75b3821459 to your computer and use it in GitHub Desktop.
avoid the view that contains adapter leak memory
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
ffun View.traverseAdapterView() { | |
depthSearchViewGroup() | |
.forEach { viewGroup -> | |
clearAdapterReference(viewGroup) | |
} | |
} | |
fun View.depthSearchViewGroup(): MutableList<ViewGroup> { | |
val viewDeque = LinkedList<View>() | |
val viewGroups = mutableListOf<ViewGroup>() | |
var view = this | |
viewDeque.push(view) | |
while (!viewDeque.isEmpty()) { | |
view = viewDeque.pop() | |
if (view is ViewGroup) { | |
viewGroups.add(view) | |
for (childIndex in 0 until view.childCount) { | |
val childView = view.getChildAt(childIndex) | |
if (childView is ViewGroup) { | |
viewDeque.push(childView) | |
} | |
} | |
} | |
} | |
return viewGroups | |
} | |
fun View.depthSearchView(): MutableList<View> { | |
val viewDeque = LinkedList<View>() | |
val views = mutableListOf<View>() | |
var view = this | |
viewDeque.push(view) | |
while (!viewDeque.isEmpty()) { | |
view = viewDeque.pop() | |
if (view is ViewGroup) { | |
for (childIndex in 0 until view.childCount) { | |
val childView = view.getChildAt(childIndex) | |
if (childView is ViewGroup) { | |
viewDeque.push(childView) | |
} else { | |
views.add(childView) | |
} | |
} | |
} | |
} | |
return views | |
} | |
private fun clearAdapterReference(viewGroup: ViewGroup): Boolean { | |
when (viewGroup) { | |
is RecyclerView -> { | |
viewGroup.clearReference() | |
return true | |
} | |
is ViewPager -> { | |
viewGroup.clearReference() | |
return true | |
} | |
is ViewPager2 -> { | |
viewGroup.clearReference() | |
return true | |
} | |
} | |
return false | |
} | |
/** | |
* Remove the adapter after the view has been detached from window in order to prevent memory leaks. | |
*/ | |
fun ViewPager.clearReference() { | |
addOnAttachStateChangeListener(object : View.OnAttachStateChangeListener { | |
override fun onViewAttachedToWindow(v: View?) { | |
} | |
override fun onViewDetachedFromWindow(v: View?) { | |
this@clearReference.adapter = null | |
removeOnAttachStateChangeListener(this) | |
} | |
}) | |
} | |
fun ViewPager2.clearReference() { | |
addOnAttachStateChangeListener(object : View.OnAttachStateChangeListener { | |
override fun onViewAttachedToWindow(v: View?) { | |
} | |
override fun onViewDetachedFromWindow(v: View?) { | |
this@clearReference.adapter = null | |
removeOnAttachStateChangeListener(this) | |
} | |
}) | |
} | |
/** | |
* Remove the adapter after the view has been detached from window in order to prevent memory leaks. | |
*/ | |
fun RecyclerView.clearReference() { | |
addOnAttachStateChangeListener(object : View.OnAttachStateChangeListener { | |
override fun onViewAttachedToWindow(v: View?) { | |
} | |
override fun onViewDetachedFromWindow(v: View?) { | |
this@clearReference.adapter = null | |
removeOnAttachStateChangeListener(this) | |
} | |
}) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
if activity or fragment use any view which contains adapter.when the adapter as a filed like this:
class Activity{
val someAdapter = ...
fun onCreate(){
recycler.adapter = someAdapter
}
}
you will leak the container.
I wrote a solved method this should call onDestory() or other destroy methods
tracing-simple-memory-leak-around-recyclerview-using-leakcanary