Provide default implementation of ViewManager#getDelegate (#48664)

Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/48664

Simplify ViewManager base-class by making `ViewManager`'s delegate non-nullable and using a single path for updating properties.

The ViewManagerDelegate API can map back to the original ViewManagerSetter API transparently, allowing us to remove the codepath from `ViewManagerPropertyUpdater`.

Changelog: [Android][Removed] `ViewManagerPropertyUpdater.updateProps` is deprected, use the related ViewManager APIs instead

Reviewed By: mdvacca, rshest

Differential Revision: D68120420

fbshipit-source-id: cd8b906dc36d4803dbe09ee0283654285eb81fd4
This commit is contained in:
Pieter De Baets
2025-01-15 04:05:47 -08:00
committed by Facebook GitHub Bot
parent 54ac150324
commit a18bc58645
2 changed files with 35 additions and 19 deletions
@@ -27,6 +27,7 @@ import com.facebook.react.uimanager.annotations.ReactPropGroup;
import com.facebook.react.uimanager.annotations.ReactPropertyHolder;
import com.facebook.yoga.YogaMeasureMode;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Stack;
@@ -41,7 +42,6 @@ public abstract class ViewManager<T extends View, C extends ReactShadowNode>
private static final String NAME = ViewManager.class.getSimpleName();
private boolean mIsDelegateLoaded = false;
private @Nullable ViewManagerDelegate<T> mDelegate = null;
/**
@@ -91,11 +91,11 @@ public abstract class ViewManager<T extends View, C extends ReactShadowNode>
* @param props {@link ReactStylesDiffMap} props to update the view with
*/
public void updateProperties(@NonNull T viewToUpdate, ReactStylesDiffMap props) {
final ViewManagerDelegate<T> delegate = getOrCreateViewManagerDelegate();
if (delegate != null) {
ViewManagerPropertyUpdater.updateProps(delegate, viewToUpdate, props);
} else {
ViewManagerPropertyUpdater.updateProps(this, viewToUpdate, props);
ViewManagerDelegate<T> delegate = getOrCreateViewManagerDelegate();
Iterator<Map.Entry<String, Object>> iterator = props.mBackingMap.getEntryIterator();
while (iterator.hasNext()) {
Map.Entry<String, Object> entry = iterator.next();
delegate.setProperty(viewToUpdate, entry.getKey(), entry.getValue());
}
onAfterUpdateTransaction(viewToUpdate);
}
@@ -106,22 +106,23 @@ public abstract class ViewManager<T extends View, C extends ReactShadowNode>
* then get calls to {@link ViewManagerDelegate#setProperty(View, String, Object)} for every prop
* that must be updated and it's the delegate's responsibility to apply these values to the view.
*
* <p>By default this method returns {@code null}, which means that the view manager doesn't have
* a delegate and the view props should be set internally by the view manager itself.
* <p>By default, this methods returns a generic {@link ViewManagerDelegate} which uses {@link
* ViewManagerSetter} to apply property updates.
*
* @return an instance of {@link ViewManagerDelegate} if the props of the view managed by this
* view manager should be set via this delegate
*/
protected @Nullable ViewManagerDelegate<T> getDelegate() {
return null;
protected ViewManagerDelegate<T> getDelegate() {
return new ViewManagerPropertyUpdater.GenericViewManagerDelegate(this);
}
private @Nullable ViewManagerDelegate<T> getOrCreateViewManagerDelegate() {
if (!mIsDelegateLoaded) {
mDelegate = getDelegate();
mIsDelegateLoaded = true;
private ViewManagerDelegate<T> getOrCreateViewManagerDelegate() {
ViewManagerDelegate<T> delegate = mDelegate;
if (delegate == null) {
delegate = getDelegate();
mDelegate = delegate;
}
return mDelegate;
return delegate;
}
/** Creates a view with knowledge of props and state. */
@@ -316,10 +317,7 @@ public abstract class ViewManager<T extends View, C extends ReactShadowNode>
* @param args optional arguments for the command
*/
public void receiveCommand(@NonNull T root, String commandId, @Nullable ReadableArray args) {
final ViewManagerDelegate<T> delegate = getOrCreateViewManagerDelegate();
if (delegate != null) {
delegate.receiveCommand(root, commandId, args);
}
getOrCreateViewManagerDelegate().receiveCommand(root, commandId, args);
}
/**
@@ -9,6 +9,8 @@ package com.facebook.react.uimanager
import android.view.View
import com.facebook.common.logging.FLog
import com.facebook.react.bridge.ReadableArray
import com.facebook.react.common.annotations.DeprecatedInNewArchitecture
import com.facebook.react.uimanager.ViewManagersPropertyCache.PropSetter
import java.util.HashMap
@@ -40,6 +42,7 @@ public object ViewManagerPropertyUpdater {
}
@JvmStatic
@Deprecated("Use ViewManager#updateProperties to update a view's properties")
public fun <T : ViewManagerDelegate<V>, V : View> updateProps(
delegate: T,
view: V,
@@ -53,6 +56,7 @@ public object ViewManagerPropertyUpdater {
}
@JvmStatic
@Deprecated("Use ViewManager#updateProperties to update a view's properties")
public fun <V : View> updateProps(
manager: ViewManager<V, *>,
view: V,
@@ -66,6 +70,7 @@ public object ViewManagerPropertyUpdater {
}
}
@DeprecatedInNewArchitecture
@JvmStatic
public fun <T : ReactShadowNode<T>> updateProps(node: T, props: ReactStylesDiffMap) {
val setter = findNodeSetter(node.javaClass)
@@ -168,4 +173,17 @@ public object ViewManagerPropertyUpdater {
}
}
}
internal class GenericViewManagerDelegate<T : View>(private val manager: ViewManager<T, *>) :
ViewManagerDelegate<T> {
private val setter = findManagerSetter(manager.javaClass)
@Suppress("ACCIDENTAL_OVERRIDE")
override fun setProperty(view: T, propName: String, value: Any?): Unit {
setter.setProperty(manager, view, propName, value)
}
@Suppress("ACCIDENTAL_OVERRIDE")
override fun receiveCommand(view: T, commandName: String, args: ReadableArray?) = Unit
}
}