[Android] Fix FastScroller leaks

Nicolas Pomepuy git at videolan.org
Thu Sep 7 08:21:02 UTC 2023


vlc-android | branch: master | Nicolas Pomepuy <nicolas at videolabs.io> | Tue Jul 25 13:43:48 2023 +0200| [6caf670274e78c4c7e6754e268cde9f58bd25b23] | committer: Nicolas Pomepuy

Fix FastScroller leaks

> https://code.videolan.org/videolan/vlc-android/commit/6caf670274e78c4c7e6754e268cde9f58bd25b23
---

 .../src/org/videolan/vlc/gui/view/FastScroller.kt  | 45 ++++++++++++++--------
 1 file changed, 29 insertions(+), 16 deletions(-)

diff --git a/application/vlc-android/src/org/videolan/vlc/gui/view/FastScroller.kt b/application/vlc-android/src/org/videolan/vlc/gui/view/FastScroller.kt
index 2092db8c6b..f129d0aa2d 100644
--- a/application/vlc-android/src/org/videolan/vlc/gui/view/FastScroller.kt
+++ b/application/vlc-android/src/org/videolan/vlc/gui/view/FastScroller.kt
@@ -72,7 +72,7 @@ private const val SHOW_SCROLLER = "show_scroller"
 
 private const val ITEM_THRESHOLD = 25
 
-class FastScroller : LinearLayout, Observer<HeadersIndex>, SchedulerCallback {
+class FastScroller : LinearLayout, Observer<HeadersIndex>, SchedulerCallback, AppBarLayout.OnOffsetChangedListener {
 
     private var currentHeight: Int = 0
     private val itemCount: Int
@@ -85,7 +85,7 @@ class FastScroller : LinearLayout, Observer<HeadersIndex>, SchedulerCallback {
     private val scrollListener = ScrollListener()
     private lateinit var recyclerView: RecyclerView
     private lateinit var layoutManager: LinearLayoutManager
-    private lateinit var provider: HeaderProvider
+    private var provider: HeaderProvider? = null
     private lateinit var handle: ImageView
     private lateinit var bubble: TextView
     private lateinit var coordinatorLayout: CoordinatorLayout
@@ -136,15 +136,7 @@ class FastScroller : LinearLayout, Observer<HeadersIndex>, SchedulerCallback {
         this.coordinatorLayout = coordinatorLayout
         appbarLayout = appBarLayout
         this.floatingActionButton = floatingActionButton
-        appBarLayout.addOnOffsetChangedListener { _, verticalOffset ->
-            layoutParams.height = coordinatorLayout.height - (appBarLayout.height + appBarLayout.top)
-            invalidate()
-            appbarLayoutExpanded = appBarLayout.top > -appBarLayout.height
-            if (appBarLayout.height == -appBarLayout.top || appBarLayout.top == 0) {
-                isAnimating.set(false)
-            }
-            lastVerticalOffset = verticalOffset
-        }
+        appBarLayout.addOnOffsetChangedListener(this)
     }
 
     override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {
@@ -221,13 +213,23 @@ class FastScroller : LinearLayout, Observer<HeadersIndex>, SchedulerCallback {
         this.layoutManager = recyclerView.layoutManager as LinearLayoutManager
         this.recyclerView.removeOnScrollListener(scrollListener)
         scheduler.startAction(HIDE_HANDLE)
-        if (this::provider.isInitialized) this.provider.liveHeaders.removeObserver(this)
+        this.provider?.liveHeaders?.removeObserver(this)
         this.provider = provider
-        provider.liveHeaders.observeForever(this)
+        provider.liveHeaders.observe(this, this)
         recyclerView.addOnScrollListener(scrollListener)
         showBubble = (recyclerView.adapter as SeparatedAdapter).hasSections()
     }
 
+    override fun onDetachedFromWindow() {
+        if (::layoutManager.isInitialized) this.layoutManager.onDetachedFromWindow(recyclerView)
+        if (::appbarLayout.isInitialized) this.appbarLayout.removeOnOffsetChangedListener(this)
+        if (::coordinatorLayout.isInitialized) this.coordinatorLayout.onDetachedFromWindow()
+        this.provider?.liveHeaders?.removeObserver(this)
+        this.provider = null
+        actor.close()
+        super.onDetachedFromWindow()
+    }
+
     /**
      * [handle] drag and drop
      */
@@ -363,9 +365,11 @@ class FastScroller : LinearLayout, Observer<HeadersIndex>, SchedulerCallback {
             //ItemDecoration has to be taken into account so we add 1 for the sticky header
             val position = layoutManager.findFirstVisibleItemPosition() + 1
             if (BuildConfig.DEBUG) Log.d(TAG, "findFirstVisibleItemPosition $position")
-            val pos = provider.getPositionForSection(position)
-            val sectionforPosition = provider.getSectionforPosition(pos)
-            if (sectionforPosition.isNotEmpty()) bubble.text = " $sectionforPosition "
+            provider?.let {
+                val pos = it.getPositionForSection(position)
+                val sectionforPosition = it.getSectionforPosition(pos)
+                if (sectionforPosition.isNotEmpty()) bubble.text = " $sectionforPosition "
+            }
             delay(100L)
         }
     }
@@ -402,4 +406,13 @@ class FastScroller : LinearLayout, Observer<HeadersIndex>, SchedulerCallback {
     }
 
     override fun getLifecycle() = findViewTreeLifecycleOwner()!!.lifecycle
+    override fun onOffsetChanged(appBar: AppBarLayout?, verticalOffset: Int) {
+        layoutParams.height = coordinatorLayout.height - (appbarLayout.height + appbarLayout.top)
+        invalidate()
+        appbarLayoutExpanded = appbarLayout.top > -appbarLayout.height
+        if (appbarLayout.height == -appbarLayout.top || appbarLayout.top == 0) {
+            isAnimating.set(false)
+        }
+        lastVerticalOffset = verticalOffset
+    }
 }



More information about the Android mailing list