Skip to content

Instantly share code, notes, and snippets.

@Haoxiqiang
Last active August 18, 2021 07:31
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Haoxiqiang/980a09aed98f410f3a7aca75b3821459 to your computer and use it in GitHub Desktop.
Save Haoxiqiang/980a09aed98f410f3a7aca75b3821459 to your computer and use it in GitHub Desktop.
avoid the view that contains adapter leak memory
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)
}
})
}
@Haoxiqiang
Copy link
Author

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment