Skip to content

Commit f951f22

Browse files
committed
fix(android): resolve Scrapped or attached views may not be recycled crash
1 parent 5a4638a commit f951f22

2 files changed

Lines changed: 35 additions & 9 deletions

File tree

android/src/main/java/com/reactnativepagerview/PagerViewViewManager.kt

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package com.reactnativepagerview
22

33
import android.view.View
44
import android.view.ViewGroup
5+
import androidx.recyclerview.widget.RecyclerView
56
import androidx.viewpager2.widget.ViewPager2
67
import androidx.viewpager2.widget.ViewPager2.OnPageChangeCallback
78
import com.facebook.infer.annotation.Assertions
@@ -88,6 +89,19 @@ class PagerViewViewManager : ViewGroupManager<NestedScrollableHost>(), RNCViewPa
8889
return host
8990
}
9091

92+
override fun onDropViewInstance(view: NestedScrollableHost) {
93+
try {
94+
val viewPager = PagerViewViewManagerImpl.getViewPager(view)
95+
val recyclerView = viewPager.getChildAt(0) as? RecyclerView
96+
recyclerView?.let {
97+
it.stopScroll()
98+
it.swapAdapter(null, false)
99+
}
100+
} catch (_: Exception) {
101+
}
102+
super.onDropViewInstance(view)
103+
}
104+
91105
override fun addView(host: NestedScrollableHost, child: View, index: Int) {
92106
PagerViewViewManagerImpl.addView(host, child, index)
93107
}
@@ -206,4 +220,4 @@ class PagerViewViewManager : ViewGroupManager<NestedScrollableHost>(), RNCViewPa
206220
PageScrollStateChangedEvent.EVENT_NAME, MapBuilder.of("registrationName", "onPageScrollStateChanged"),
207221
PageSelectedEvent.EVENT_NAME, MapBuilder.of("registrationName", "onPageSelected"))
208222
}
209-
}
223+
}

android/src/main/java/com/reactnativepagerview/ViewPagerAdapter.kt

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -17,19 +17,28 @@ class ViewPagerAdapter() : Adapter<ViewPagerViewHolder>() {
1717
override fun onBindViewHolder(holder: ViewPagerViewHolder, index: Int) {
1818
val container: FrameLayout = holder.container
1919
val child = getChildAt(index)
20-
holder.setIsRecyclable(false)
2120

2221
if (container.childCount > 0) {
2322
container.removeAllViews()
2423
}
2524

2625
if (child.parent != null) {
27-
(child.parent as FrameLayout).removeView(child)
26+
(child.parent as ViewGroup).removeView(child)
2827
}
2928

3029
container.addView(child)
3130
}
3231

32+
override fun onViewRecycled(holder: ViewPagerViewHolder) {
33+
super.onViewRecycled(holder)
34+
holder.container.removeAllViews()
35+
}
36+
37+
override fun onFailedToRecycleView(holder: ViewPagerViewHolder): Boolean {
38+
holder.container.removeAllViews()
39+
return true
40+
}
41+
3342
override fun getItemCount(): Int {
3443
return childrenViews.size
3544
}
@@ -45,17 +54,16 @@ class ViewPagerAdapter() : Adapter<ViewPagerViewHolder>() {
4554

4655
fun removeChild(child: View) {
4756
val index = childrenViews.indexOf(child)
48-
57+
4958
if(index > -1) {
5059
removeChildAt(index)
5160
}
5261
}
5362

5463
fun removeAll() {
55-
for (index in 1..childrenViews.size) {
56-
val child = childrenViews[index-1]
57-
if (child.parent?.parent != null) {
58-
(child.parent.parent as ViewGroup).removeView(child.parent as View)
64+
for (child in childrenViews) {
65+
if (child.parent != null) {
66+
(child.parent as ViewGroup).removeView(child)
5967
}
6068
}
6169
val removedChildrenCount = childrenViews.size
@@ -64,7 +72,11 @@ class ViewPagerAdapter() : Adapter<ViewPagerViewHolder>() {
6472
}
6573

6674
fun removeChildAt(index: Int) {
67-
if (index >= 0 && index < childrenViews.size) {
75+
if (index >= 0 && index < childrenViews.size) {
76+
val child = childrenViews[index]
77+
if (child.parent != null) {
78+
(child.parent as ViewGroup).removeView(child)
79+
}
6880
childrenViews.removeAt(index)
6981
notifyItemRemoved(index)
7082
}

0 commit comments

Comments
 (0)