继续上一篇分析下面方法调用
- createView
- setChildren
- manageChildren
- onBatchComplete
讲完ReactShadowNode了我们可以看看createView,主要分3 步:
- ①创建与JS侧对应的ReactShadowNode节点
- ②updateProperties设置ReactShadowNode节点的属性
- ③handleCreateView创建VIew
//UIImplementation.java
public void createView(int tag, String className, int rootViewTag, ReadableMap props) {
synchronized (uiImplementationThreadLock) {
//①
ReactShadowNode cssNode = createShadowNode(className);
ReactShadowNode rootNode = mShadowNodeRegistry.getNode(rootViewTag);
Assertions.assertNotNull(rootNode, "Root node with tag " + rootViewTag + " doesn't exist" );
cssNode.setReactTag(tag); // Thread safety needed here
cssNode.setViewClassName(className);
cssNode.setRootTag(rootNode.getReactTag());
cssNode.setThemedContext(rootNode.getThemedContext());
mShadowNodeRegistry.addNode(cssNode);
ReactStylesDiffMap styles = null;
if (props != null) {
styles = new ReactStylesDiffMap(props);
//②
cssNode.updateProperties(styles);
}
//③
handleCreateView(cssNode, rootViewTag, styles);
}
}
创建ShadowNode节点
第①点createShadowNode:
先看看createShadowNode
protected ReactShadowNode createShadowNode(String className) {
ViewManager viewManager = mViewManagers.get(className);
return viewManager.createShadowNodeInstance(mReactContext);
}
mViewManagers是ViewManagerRegistry
- 先从缓存mViewManagers中查找
- 如果没有调用getViewManagerFromResolver进行检索
public synchronized ViewManager get(String className) {
// 1. Try to get the manager without the prefix.
ViewManager viewManager = mViewManagers.get(className);
if (viewManager != null) {
return viewManager;
}
// 2. Try to get the manager with the RCT prefix.
String rctViewManagerName = "RCT" + className;
viewManager = mViewManagers.get(rctViewManagerName);
if (viewManager != null) {
return viewManager;
}
if (mViewManagerResolver != null) {
// 1. Try to get the manager without the prefix.
viewManager = getViewManagerFromResolver(className);
if (viewManager != null) return viewManager;
// 2. Try to get the manager with the RCT prefix.
viewManager = getViewManagerFromResolver(rctViewManagerName);
if (viewManager != null) return viewManager;
...
}
}
getViewManagerFromResolver方法如下,重点是mViewManagerResolver是什么
private @Nullable ViewManager getViewManagerFromResolver(String className) {
@Nullable ViewManager viewManager;
viewManager = mViewManagerResolver.getViewManager(className);
if (viewManager != null) {
mViewManagers.put(className, viewManager);
}
return viewManager;
}
在《UIManagerModule构造函数》我们分析了mViewManagerResolver实际是
ViewManagerResolver resolver =
new ViewManagerResolver() {
@Override
public @Nullable ViewManager getViewManager(String viewManagerName) {
return mReactInstanceManager.createViewManager(viewManagerName);
}
@Override
public Collection<String> getViewManagerNames() {
return mReactInstanceManager.getViewManagerNames();
}
};
也就是getViewManager最终调用的是mReactInstanceManager.createViewManager
public @Nullable ViewManager createViewManager(String viewManagerName) {
...
synchronized (mPackages) {
for (ReactPackage reactPackage : mPackages) {
if (reactPackage instanceof ViewManagerOnDemandReactPackage) {
ViewManager viewManager =
((ViewManagerOnDemandReactPackage) reactPackage)
.createViewManager(context, viewManagerName);
if (viewManager != null) {
return viewManager;
}
}
}
}
return null;
}
在createViewManager中会根据viewManagerName查找到对应的ViewManager,以RCTRawText为例
| RN组件 | className | ShadowNode | View | ViewManager |
|---|---|---|---|---|
| Text | RCTText | ReactTextShadowNode | ReactTextView | ReactTextViewManager |
| View | RCTView | LayoutShadowNode | ReactViewGroup | ReactViewManager |
@VisibleForTesting public static final String REACT_CLASS = "RCTText" ;
@ReactModule(name = ReactTextViewManager.REACT_CLASS)
public class ReactTextViewManager
extends ReactTextAnchorViewManager<ReactTextView, ReactTextShadowNode>
implements IViewManagerWithChildren
所以在这个案例中mViewManagers.get(className)返回的是ReactTextViewManager,继续看看createShadowNodeInstance
@Override
public ReactTextShadowNode createShadowNodeInstance() {
return new ReactTextShadowNode(mReactTextViewManagerCallback);
}
ReactTextShadowNode是ReactShadowNodeImpl的子类,这就是在上一篇《ReactShadowNode》中分析,JS中的节点会映射到ReactTextShadowNode,然后形成 4 棵树。
设置属性
第②点updateProperties:
public static <T extends ReactShadowNode> void updateProps(T node, ReactStylesDiffMap props) {
ShadowNodeSetter<T> setter = findNodeSetter(node.getClass());
Iterator<Map.Entry<String, Object>> iterator = props.mBackingMap.getEntryIterator();
while (iterator.hasNext()) {
Map.Entry<String, Object> entry = iterator.next();
setter.setProperty(node, entry.getKey(), entry.getValue());
}
}
调用findNodeSetter查找ShadowNodeSetter
- SHADOW_NODE_SETTER_MAP缓存加速作用
- 调用findGeneratedSetter获取ShadowNodeSetter
- 如果没找到使用默认的FallbackShadowNodeSetter
private static <T extends ReactShadowNode> ShadowNodeSetter<T> findNodeSetter(
Class<? extends ReactShadowNode> nodeClass) {
@SuppressWarnings( "unchecked" )
ShadowNodeSetter<T> setter = (ShadowNodeSetter<T>) SHADOW_NODE_SETTER_MAP.get(nodeClass);
if (setter == null) {
setter = findGeneratedSetter(nodeClass);
if (setter == null) {
setter = new FallbackShadowNodeSetter<>(nodeClass);
}
SHADOW_NODE_SETTER_MAP.put(nodeClass, setter);
}
return setter;
}
findGeneratedSetter通过反射查找名字为 "RCTText$$PropsSetter" 的类(以前面RCTText为例)
private static <T> T findGeneratedSetter(Class<?> cls) {
String clsName = cls.getName();
try {
Class<?> setterClass = Class.forName(clsName + "$$PropsSetter" );
//noinspection unchecked
return (T) setterClass.newInstance();
} catch (ClassNotFoundException e) {
FLog.w(TAG, "Could not find generated setter for " + cls);
return null;
} catch (InstantiationException | IllegalAccessException e) {
throw new RuntimeException( "Unable to instantiate methods getter for " + clsName, e);
}
}
那 **"RCTTextPropsSetter,并实现 ShadowNodeSetter,内部是 switch(name)直接调node.xxx(...),避免反射比稿效率。ReactTextViewManager是继承ViewManager,而ViewManager用注解@ReactPropertyHolder`修饰的
@ReactModule(name = ReactTextViewManager.REACT_CLASS)
public class ReactTextViewManager
extends ReactTextAnchorViewManager<ReactTextView, ReactTextShadowNode>
implements IViewManagerWithChildren
@ReactPropertyHolder
public abstract class ViewManager<T extends View, C extends ReactShadowNode>
extends BaseJavaModule
在 "RCTText$$PropsSetter" 类中实现了ShadowNodeSetter接口,其实现的内部是 switch(name) 直接调 ReactShadowNode.xxx(...)
public interface ShadowNodeSetter<T extends ReactShadowNode> extends Settable {
void setProperty(T node, String name, Object value);
}
那么这个switch(name)是如何构建实现的呢?它是注解处理器解析ViewManager中的@ReactProp属性实现的
@ReactModule(name = ReactTextViewManager.REACT_CLASS)
public class ReactTextViewManager
extends ReactTextAnchorViewManager<ReactTextView, ReactTextShadowNode>
implements IViewManagerWithChildren {
@ReactProp(name = "overflow" )
public void setOverflow(ReactTextView view, @Nullable String overflow) {
view.setOverflow(overflow);
}
}
//父类
@ReactModule(name = ReactTextViewManager.REACT_CLASS)
public class ReactTextViewManager
extends ReactTextAnchorViewManager<ReactTextView, ReactTextShadowNode>
implements IViewManagerWithChildren {
@ReactProp(name = ViewProps.ADJUSTS_FONT_SIZE_TO_FIT)
public void setAdjustFontSizeToFit(ReactTextView view, boolean adjustsFontSizeToFit) {
view.setAdjustFontSizeToFit(adjustsFontSizeToFit);
}
@ReactProp(name = ViewProps.FONT_SIZE)
public void setFontSize(ReactTextView view, float fontSize) {
view.setFontSize(fontSize);
}
}
- 当JS中设置了overflow属性——>RCTText$$PropsSetter.setProperty——>ReactTextShadowNode.setOverflow
- ReactTextShadowNode.setOverflow是在父类LayoutShadowNode中实现的
@ReactProp(name = ViewProps.OVERFLOW)
public void setOverflow(@Nullable String overflow)
创建Native View
第③点handleCreateView:
protected void handleCreateView(
ReactShadowNode cssNode, int rootViewTag, @Nullable ReactStylesDiffMap styles) {
if (!cssNode.isVirtual()) {
mNativeViewHierarchyOptimizer.handleCreateView(cssNode, cssNode.getThemedContext(), styles);
}
}
逻辑:只对非虚拟节点执行。虚拟节点(如嵌套文本 <Text> 内的 <Text>)不映射到原生 View,直接跳过。
public boolean isVirtual() { return false; }
默认返回 false。只有 ReactTextShadowNode、ReactRawTextShadowNode 等子类会覆盖为 true。虚拟节点:
- 不创建 YogaNode(
mYogaNode = null) - 不参与 Yoga 布局计算
- 不映射到任何原生 View
视图层级优化器:NativeViewHierarchyOptimizer#handleCreateView
-
判断节点是否是纯布局节点,如果是虚拟节点或纯布局节点,无原生 View
-
三种 NativeKind
- NONE — 虚拟节点或纯布局节点,无原生 View
- LEAF — 无子节点,需要原生 View
- PARENT — 有子节点,需要原生 ViewGroup
public void handleCreateView(
ReactShadowNode node,
ThemedReactContext themedContext,
@Nullable ReactStylesDiffMap initialProps) {
....
boolean isLayoutOnly =
node.getViewClass().equals(ViewProps.VIEW_CLASS_NAME)
&& isLayoutOnlyAndCollapsable(initialProps);
node.setIsLayoutOnly(isLayoutOnly);
if (node.getNativeKind() != NativeKind.NONE) {
mUIViewOperationQueue.enqueueCreateView(
themedContext, node.getReactTag(), node.getViewClass(), initialProps);
}
}
向mNonBatchedOperations队列中添加了一个CreateViewOperation
public void enqueueCreateView(
ThemedReactContext themedContext,
int viewReactTag,
String viewClassName,
@Nullable ReactStylesDiffMap initialProps) {
synchronized (mNonBatchedOperationsLock) {
mCreateViewCount++;
mNonBatchedOperations.addLast(
new CreateViewOperation(themedContext, viewReactTag, viewClassName, initialProps));
}
}
mNonBatchedOperations队列在某个时机会被统一调度,这个调度时机后面会进行分析,我们继续看CreateViewOperation,它调用mNativeViewHierarchyManager.createView
public synchronized void createView(
ThemedReactContext themedContext,
int tag,
String className,
@Nullable ReactStylesDiffMap initialProps) {
try {
ViewManager viewManager = mViewManagers.get(className);
View view =
viewManager.createView(tag, themedContext, initialProps, null, mJSResponderHandler);
mTagsToViews.put(tag, view);
mTagsToViewManagers.put(tag, viewManager);
} finally {
Systrace.endSection(Systrace.TRACE_TAG_REACT_VIEW);
}
}
调用createView中会调用createViewInstance创建Native VIew
protected @NonNull T createViewInstance(
int reactTag,
@NonNull ThemedReactContext reactContext,
@Nullable ReactStylesDiffMap initialProps,
@Nullable StateWrapper stateWrapper) {
T view = null;
@Nullable Stack<T> recyclableViews = getRecyclableViewStack(reactContext.getSurfaceId(), true);
if (recyclableViews != null && !recyclableViews.empty()) {
view = recycleView(reactContext, recyclableViews.pop());
} else {
//创建View
view = createViewInstance(reactContext);
}
//设置id
view.setId(reactTag);
...
return view;
}
createViewInstance是一个抽象方法,每一个实现ViewManager接口的类都必须实现这个方法
protected abstract @NonNull T createViewInstance(@NonNull ThemedReactContext reactContext);
对于ReactTextViewManager的实现如下,这里返回了真正的Native View
@Override
public ReactTextView createViewInstance(ThemedReactContext context) {
return new ReactTextView(context);
}
最后将tag与view、viewManager关系使用mTagsToViews和mTagsToViewManagers记录下来。