@@ -124,78 +124,25 @@ class PagerViewViewManager :
124124 }
125125
126126 override fun onDropViewInstance (view : NestedScrollableHost ) {
127- try {
128- val viewPager = PagerViewViewManagerImpl .getViewPager(view)
129- // Access private mRecyclerView field using reflection
130- val recyclerViewField = ViewPager2 ::class .java.getDeclaredField(" mRecyclerView" )
131- recyclerViewField.isAccessible = true
132- val recyclerView = recyclerViewField.get(viewPager) as RecyclerView
133-
134- // Stop any scroll/drag in progress first
135- recyclerView.stopScroll()
136-
137- // Suppress layout to prevent any pending layout operations from executing
138- recyclerView.suppressLayout(true )
139-
140- // Access and stop the ViewFlinger directly via reflection - do this early
141- try {
142- val viewFlingerField = RecyclerView ::class .java.getDeclaredField(" mViewFlinger" )
143- viewFlingerField.isAccessible = true
144- val viewFlinger = viewFlingerField.get(recyclerView) as ? Runnable
145- viewFlinger?.let {
146- recyclerView.removeCallbacks(it)
147- // Also try to stop it via reflection if it has a stop method
148- try {
149- val stopMethod = viewFlinger.javaClass.getDeclaredMethod(" stop" )
150- stopMethod.isAccessible = true
151- stopMethod.invoke(viewFlinger)
152- } catch (ignored: Exception ) {}
153- }
154- } catch (ignored: Exception ) {
155- // ViewFlinger reflection may fail on some versions
156- }
127+ val vp = view.getChildAt(0 ) as ? ViewPager2
128+ val recyclerView = vp?.getChildAt(0 ) as ? RecyclerView
157129
158- // Clear the recycler's scrap views before clearing adapter
159- try {
160- val recyclerField = RecyclerView ::class .java.getDeclaredField(" mRecycler" )
161- recyclerField.isAccessible = true
162- val recycler = recyclerField.get(recyclerView)
163-
164- // Clear scrap heaps
165- val clearScrapMethod = recycler.javaClass.getDeclaredMethod(" clear" )
166- clearScrapMethod.isAccessible = true
167- clearScrapMethod.invoke(recycler)
168- } catch (ignored: Exception ) {
169- // Recycler reflection may fail on some versions
170- }
130+ // Stop any in-progress scroll/fling
131+ recyclerView?.stopScroll()
171132
172- // Clear any pending animations and layout transitions
173- recyclerView.clearAnimation()
174- recyclerView.itemAnimator = null
175- recyclerView.layoutTransition = null
176- recyclerView.recycledViewPool.clear()
177-
178- // Remove all pending operations and choreographer callbacks
179- recyclerView.removeCallbacks(null )
180-
181- // Try to clear any pending adapter updates
182- try {
183- val adapterHelperField = RecyclerView ::class .java.getDeclaredField(" mAdapterHelper" )
184- adapterHelperField.isAccessible = true
185- val adapterHelper = adapterHelperField.get(recyclerView)
186- val resetMethod = adapterHelper.javaClass.getDeclaredMethod(" reset" )
187- resetMethod.isAccessible = true
188- resetMethod.invoke(adapterHelper)
189- } catch (ignored: Exception ) {}
190-
191- // Clear the adapter to prevent recycling during teardown
192- viewPager.adapter = null
193-
194- // Unsuppress layout after clearing adapter (won't do anything as view is being
195- // destroyed)
196- recyclerView.suppressLayout(false )
197- } catch (e: Exception ) {
198- // View might already be in an invalid state
133+ // Disable item animations to prevent animator callbacks during teardown
134+ recyclerView?.itemAnimator = null
135+
136+ // Clear cached views in the recycled pool
137+ recyclerView?.recycledViewPool?.clear()
138+
139+ try {
140+ // Clear adapter to prevent post-teardown fling callbacks.
141+ // setAdapter(null) internally calls removeAndRecycleAllViews which
142+ // can throw if views are still attached during mid-scroll teardown.
143+ recyclerView?.adapter = null
144+ } catch (_: IllegalArgumentException ) {
145+ // Safe to ignore during teardown — view is being destroyed
199146 }
200147 super .onDropViewInstance(view)
201148 }
0 commit comments