diff --git a/packages/react-native/ReactAndroid/api/ReactAndroid.api b/packages/react-native/ReactAndroid/api/ReactAndroid.api index 7d27ba44c69..8cc66c6cd97 100644 --- a/packages/react-native/ReactAndroid/api/ReactAndroid.api +++ b/packages/react-native/ReactAndroid/api/ReactAndroid.api @@ -5286,7 +5286,7 @@ public abstract class com/facebook/react/uimanager/ViewManager : com/facebook/re protected fun onAfterUpdateTransaction (Landroid/view/View;)V public fun onDropViewInstance (Landroid/view/View;)V public fun onSurfaceStopped (I)V - protected fun prepareToRecycleView (Lcom/facebook/react/uimanager/ThemedReactContext;Landroid/view/View;)Landroid/view/View; + protected abstract fun prepareToRecycleView (Lcom/facebook/react/uimanager/ThemedReactContext;Landroid/view/View;)Landroid/view/View; public fun receiveCommand (Landroid/view/View;ILcom/facebook/react/bridge/ReadableArray;)V public fun receiveCommand (Landroid/view/View;Ljava/lang/String;Lcom/facebook/react/bridge/ReadableArray;)V protected fun recycleView (Lcom/facebook/react/uimanager/ThemedReactContext;Landroid/view/View;)Landroid/view/View; @@ -7266,6 +7266,7 @@ public class com/facebook/react/views/text/ReactRawTextManager : com/facebook/re public fun createViewInstance (Lcom/facebook/react/uimanager/ThemedReactContext;)Lcom/facebook/react/views/text/ReactTextView; public fun getName ()Ljava/lang/String; public fun getShadowNodeClass ()Ljava/lang/Class; + protected fun prepareToRecycleView (Lcom/facebook/react/uimanager/ThemedReactContext;Landroid/view/View;)Landroid/view/View; public fun updateExtraData (Landroid/view/View;Ljava/lang/Object;)V } diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/BaseViewManager.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/BaseViewManager.java index 84bf68d23d0..28262eb7ce1 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/BaseViewManager.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/BaseViewManager.java @@ -68,7 +68,7 @@ public abstract class BaseViewManager= Build.VERSION_CODES.P) { + view.resetPivot(); + } else { + // no way of resetting pivot, or knowing whether it is set + return null; + } view.setTop(0); view.setBottom(0); view.setLeft(0); view.setRight(0); view.setElevation(0); - view.setAnimationMatrix(null); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { + // failsafe - should already be set to null when animation finishes + view.setAnimationMatrix(null); + } view.setTag(R.id.transform, null); view.setTag(R.id.transform_origin, null); diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/ViewManager.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/ViewManager.java index aedc311fa38..7ebe7909d94 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/ViewManager.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/ViewManager.java @@ -226,16 +226,20 @@ public abstract class ViewManager int surfaceId = themedReactContext.getSurfaceId(); @Nullable Stack recyclableViews = getRecyclableViewStack(surfaceId); if (recyclableViews != null) { - recyclableViews.push(prepareToRecycleView(themedReactContext, view)); + T recyclableView = prepareToRecycleView(themedReactContext, view); + if (recyclableView != null) { + recyclableViews.push(recyclableView); + } } } /** * Called when a View is removed from the hierarchy. This should be used to reset any properties. + * + * @return {@code view} if it was properly recycled, or {@code null} if it could not be recycled */ - protected T prepareToRecycleView(@NonNull ThemedReactContext reactContext, @NonNull T view) { - return view; - } + protected abstract @Nullable T prepareToRecycleView( + @NonNull ThemedReactContext reactContext, @NonNull T view); /** Called when a View is going to be reused. */ protected T recycleView(@NonNull ThemedReactContext reactContext, @NonNull T view) { diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactRawTextManager.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactRawTextManager.java index 4a6901198f0..4c2a87352f4 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactRawTextManager.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactRawTextManager.java @@ -8,6 +8,8 @@ package com.facebook.react.views.text; import android.view.View; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; import com.facebook.react.common.annotations.VisibleForTesting; import com.facebook.react.module.annotations.ReactModule; import com.facebook.react.uimanager.ThemedReactContext; @@ -32,6 +34,12 @@ public class ReactRawTextManager extends ViewManager { } @Override - protected ReactViewGroup prepareToRecycleView( + protected @Nullable ReactViewGroup prepareToRecycleView( @NonNull ThemedReactContext reactContext, ReactViewGroup view) { // BaseViewManager - super.prepareToRecycleView(reactContext, view); - - view.recycleView(); - + ReactViewGroup preparedView = super.prepareToRecycleView(reactContext, view); + if (preparedView != null) { + preparedView.recycleView(); + } return view; } diff --git a/packages/react-native/ReactAndroid/src/test/java/com/facebook/react/uimanager/ReactPropAnnotationSetterSpecTest.kt b/packages/react-native/ReactAndroid/src/test/java/com/facebook/react/uimanager/ReactPropAnnotationSetterSpecTest.kt index dbd41441dfc..130531a81ef 100644 --- a/packages/react-native/ReactAndroid/src/test/java/com/facebook/react/uimanager/ReactPropAnnotationSetterSpecTest.kt +++ b/packages/react-native/ReactAndroid/src/test/java/com/facebook/react/uimanager/ReactPropAnnotationSetterSpecTest.kt @@ -29,6 +29,8 @@ class ReactPropAnnotationSetterSpecTest { override fun createViewInstance(reactContext: ThemedReactContext): View = createViewInstance(reactContext) + override fun prepareToRecycleView(reactContext: ThemedReactContext, view: View): View? = null + override fun updateExtraData(root: View, extraData: Any) = Unit } diff --git a/packages/react-native/ReactAndroid/src/test/java/com/facebook/react/uimanager/ReactPropAnnotationSetterTest.kt b/packages/react-native/ReactAndroid/src/test/java/com/facebook/react/uimanager/ReactPropAnnotationSetterTest.kt index 996a7617432..8c39f9f9579 100644 --- a/packages/react-native/ReactAndroid/src/test/java/com/facebook/react/uimanager/ReactPropAnnotationSetterTest.kt +++ b/packages/react-native/ReactAndroid/src/test/java/com/facebook/react/uimanager/ReactPropAnnotationSetterTest.kt @@ -65,6 +65,10 @@ class ReactPropAnnotationSetterTest { override fun createViewInstance(reactContext: ThemedReactContext): View = error("This method should not be executed as a part of this test") + override fun prepareToRecycleView(reactContext: ThemedReactContext, view: View): View? { + error("This method should not be executed as a part of this test") + } + override fun updateExtraData(root: View, extraData: Any) = error("This method should not be executed as a part of this test") diff --git a/packages/react-native/ReactAndroid/src/test/java/com/facebook/react/uimanager/ReactPropConstantsTest.kt b/packages/react-native/ReactAndroid/src/test/java/com/facebook/react/uimanager/ReactPropConstantsTest.kt index 37a700aa3bb..7b2c341c2c7 100644 --- a/packages/react-native/ReactAndroid/src/test/java/com/facebook/react/uimanager/ReactPropConstantsTest.kt +++ b/packages/react-native/ReactAndroid/src/test/java/com/facebook/react/uimanager/ReactPropConstantsTest.kt @@ -37,6 +37,10 @@ class ReactPropConstantsTest { error("This method should not be executed as a part of this test") } + override fun prepareToRecycleView(reactContext: ThemedReactContext, view: View): View? { + error("This method should not be executed as a part of this test") + } + override fun getShadowNodeClass(): Class> { return ReactShadowNode::class.java } diff --git a/packages/react-native/ReactAndroid/src/test/java/com/facebook/react/uimanager/ReactPropForShadowNodeSpecTest.kt b/packages/react-native/ReactAndroid/src/test/java/com/facebook/react/uimanager/ReactPropForShadowNodeSpecTest.kt index 33b81f311c5..accfd039d9f 100644 --- a/packages/react-native/ReactAndroid/src/test/java/com/facebook/react/uimanager/ReactPropForShadowNodeSpecTest.kt +++ b/packages/react-native/ReactAndroid/src/test/java/com/facebook/react/uimanager/ReactPropForShadowNodeSpecTest.kt @@ -110,6 +110,8 @@ class ReactPropForShadowNodeSpecTest { override fun createViewInstance(reactContext: ThemedReactContext): View = View(null) + override fun prepareToRecycleView(reactContext: ThemedReactContext, view: View): View? = null + override fun updateExtraData(root: View, extraData: Any?) = Unit } }