ReactNative Fabric渲染器和组件(5)
ReactNative Fabric渲染器和组件
简述
Fabric是ReactNative中新架构最核心的模块,本章我们会来了解一下自定义一个Fabric组件,然后在JS文件中声明之后如何,是怎么映射到原生构建一个View的。
关于Fabric架构理念官网已经有说明了,我们就不细说了,从实现来说,就是在JS层会有一套DOM树,这个是基于React实现的,然后在C++层会构建出一个ShadowTree,由一个个ShadowNode组成的树,最终会映射到原生的View。
Demo
和TurboModule一样,我们也先按照官网流程生成一个自定义的Fabric组件,然后后面我们在JS中去使用它,最终来看看它的构建流程。
我们定义一个JS文件,然后使用使用Codegen生成脚手架。
// @flow strict-local
import type {ViewProps} from 'react-native/Libraries/Components/View/ViewPropTypes';
import type {HostComponent} from 'react-native';
import codegenNativeComponent from 'react-native/Libraries/Utilities/codegenNativeComponent';
type NativeProps = $ReadOnly<{|
...ViewProps,
text: ?string,
// add other props here
|}>;
export default (codegenNativeComponent<NativeProps>(
'RTNTestView',
): HostComponent<NativeProps>);
生成的代码如下:
入口
我们从index.js开始看,我们会省略一些React的逻辑,主要是看一下RN在Android上的流程,而对React对DOM对构建和管理不是我们所关心的。
1.1 index.js
入口调用了AppRegistry.registerComponent,() => App是我们写UI布局的地方,我们知道RN使用了JSX语法,我们
AppRegistry.registerComponent(appName, () => App);
1.2 AppRegistry.registerComponent
主要是调用了renderApplication
registerComponent(
appKey: string,
componentProvider: ComponentProvider,
section?: boolean,
): string {
const scopedPerformanceLogger = createPerformanceLogger();
runnables[appKey] = (appParameters, displayMode) => {
const concurrentRootEnabled = Boolean(
appParameters.initialProps?.concurrentRoot ||
appParameters.concurrentRoot,
);
// 详见1.3
renderApplication(
componentProviderInstrumentationHook(
componentProvider,
scopedPerformanceLogger,
),
appParameters.initialProps,
appParameters.rootTag,
wrapperComponentProvider && wrapperComponentProvider(appParameters),
rootViewStyleProvider && rootViewStyleProvider(appParameters),
appParameters.fabric,
scopedPerformanceLogger,
appKey === 'LogBox', // is logbox
appKey,
displayMode,
concurrentRootEnabled,
);
};
if (section) {
sections[appKey] = runnables[appKey];
}
return appKey;
}
1.3 renderApplication
export default function renderApplication<Props: Object>(
RootComponent: React.ComponentType<Props>,
initialProps: Props,
rootTag: any,
WrapperComponent?: ?React.ComponentType<any>,
rootViewStyle?: ?ViewStyleProp,
fabric?: boolean,
scopedPerformanceLogger?: IPerformanceLogger,
isLogBox?: boolean,
debugName?: string,
displayMode?: ?DisplayModeType,
useConcurrentRoot?: boolean,
useOffscreen?: boolean,
) {
invariant(rootTag, 'Expect to have a valid rootTag, instead got ', rootTag);
const performanceLogger = scopedPerformanceLogger ?? GlobalPerformanceLogger;
// 这里将传入的RootComponent外面包了两层
let renderable: React.MixedElement = (
<PerformanceLoggerContext.Provider value={performanceLogger}>
<AppContainer
rootTag={rootTag}
fabric={fabric}
WrapperComponent={WrapperComponent}
rootViewStyle={rootViewStyle}
initialProps={initialProps ?? Object.freeze({})}
internal_excludeLogBox={isLogBox}>
<RootComponent {...initialProps} rootTag={rootTag} />
</AppContainer>
</PerformanceLoggerContext.Provider>
);
// ...debug相关操作
if (useOffscreen && displayMode != null) {
// $FlowFixMe[incompatible-type]
// $FlowFixMe[prop-missing]
const Activity: ActivityType = React.unstable_Activity;
renderable = (
<Activity
mode={displayMode === DisplayMode.VISIBLE ? 'visible' : 'hidden'}>
{renderable}
</Activity>
);
}
// We want to have concurrentRoot always enabled when you're on Fabric.
const useConcurrentRootOverride = fabric;
// ... 性能日志
// 渲染element,renderable是我们在app.js定义的UI并且在外面套上AppContainer和PerformanceLoggerContext.Provider生成的Element树的根节点。
// 详见1.4
Renderer.renderElement({
element: renderable,
rootTag,
useFabric: Boolean(fabric),
useConcurrentRoot: Boolean(useConcurrentRootOverride),
});
// ... 性能日志
}
1.4 renderElement
这里就是判断一下使用新渲染器Fabric还是以前的渲染器,我们这里跟Fabric的。
ReactFabric会根据是否是dev(debug)来决定使用ReactFabric-dev还是ReactFabric-prod,区别就是dev会有一些调试能力。
我们来看ReactFabric-prod里的render。
export function renderElement({
element,
rootTag,
useFabric,
useConcurrentRoot,
}: {
element: React.MixedElement,
rootTag: number,
useFabric: boolean,
useConcurrentRoot: boolean,
}): void {
if (useFabric) {
// 详见1.5
require('../Renderer/shims/ReactFabric').render(
element,
rootTag,
null,
useConcurrentRoot,
{
onCaughtError,
onUncaughtError,
onRecoverableError,
},
);
} else {
require('../Renderer/shims/ReactNative').render(
element,
rootTag,
undefined,
{
onCaughtError,
onUncaughtError,
onRecoverableError,
},
);
}
}
1.5 render
这个文件里逻辑也可以不用太关心,这里主要是处理树的数据结构构造和更新,加上源码里一堆魔数,看不懂~,主要看一下流程。
接下来我们直接跳到这个文件里创建ShadowNode的地方。
exports.render = function (
element,
containerTag,
callback,
concurrentRoot,
options
) {
// roots是一个Map缓存
var root = roots.get(containerTag);
// 如果之前没有这个root节点,需要新建
if (!root) {
root = nativeOnUncaughtError;
var onCaughtError = nativeOnCaughtError,
onRecoverableError = defaultOnRecoverableError;
options &&
void 0 !== options.onUncaughtError &&
(root = options.onUncaughtError);
options &&
void 0 !== options.onCaughtError &&
(onCaughtError = options.onCaughtError);
options &&
void 0 !== options.onRecoverableError &&
(onRecoverableError = options.onRecoverableError);
concurrentRoot = concurrentRoot ? 1 : 0;
// 新建Fiber root节点
options = new FiberRootNode(
containerTag,
concurrentRoot,
!1,
"",
root,
onCaughtError,
onRecoverableError,
null
);
// 新建Fiber节点
concurrentRoot = createFiber(3, null, null, 1 === concurrentRoot ? 1 : 0);
options.current = concurrentRoot;
concurrentRoot.stateNode = options;
root = createCache();
root.refCount++;
options.pooledCache = root;
root.refCount++;
concurrentRoot.memoizedState = {
element: null,
isDehydrated: !1,
cache: root
};
initializeUpdateQueue(concurrentRoot);
root = options;
roots.set(containerTag, root);
}
// 触发更新
updateContainer(element, root, null, callback);
a: if (((element = root.current), element.child))
switch (element.child.tag) {
case 27:
case 5:
element = getPublicInstance(element.child.stateNode);
break a;
default:
element = element.child.stateNode;
}
else element = null;
return element;
};
1.6 completeWork
调用createNode来创建Shadow节点,uiViewClassName则是我们最早在JS中声明的,以我们自定义的Fabric组件为例就是RTNTestView
这里的createNode是nativeFabricUIManager里的createNode,而nativeFabricUIManager是一个native对象,通过JSI加载进来的,加载的代码在UIManagerBinding.cpp中,看过之前TurboModule加载和JSI的章节的话,很容易可以看懂这里的逻辑,详见1.6.1
function completeWork(current, workInProgress, renderLanes) {
// ...
// 详见1.7
oldProps = createNode(
current,
renderLanes.uiViewClassName,
oldProps,
updatePayload,
workInProgress
);
// ...
}
nativeFabricUIManage = nativeFabricUIManager,
createNode = _nativeFabricUIManage.createNode,
1.6.1 UIManagerBinding::createAndInstallIfNeeded
这里就是将JS nativeFabricUIManager和UIManagerBinding关联,所以我们要来看一下UIManagerBinding的get方法,看一下createNode是怎么定义的。
void UIManagerBinding::createAndInstallIfNeeded(
jsi::Runtime& runtime,
const std::shared_ptr<UIManager>& uiManager) {
auto uiManagerModuleName = "nativeFabricUIManager";
auto uiManagerValue =
runtime.global().getProperty(runtime, uiManagerModuleName);
// 如果之前已经设置过了不重复设置
if (uiManagerValue.isUndefined()) {
auto uiManagerBinding = std::make_shared<UIManagerBinding>(uiManager);
auto object = jsi::Object::createFromHostObject(runtime, uiManagerBinding);
// 通过JSI接口设置全局global的属性nativeFabricUIManager为native的uiManagerBinding
runtime.global().setProperty(
runtime, uiManagerModuleName, std::move(object));
}
}
1.7 UIManagerBinding::get
createNode调用了uiManager->createNode来构造ShadowNode,然后把ShadowNode封装到JSI::Vaule返回给JS层。
这里的uiManager是一个UIManager实例,UIManagerBinding和UIManager是在FabricUIManager模块加载时,加载SurfaceManager,里面构造Schudler的时候进行绑定的。
jsi::Value UIManagerBinding::get(
jsi::Runtime& runtime,
const jsi::PropNameID& name) {
auto methodName = name.utf8(runtime);
UIManager* uiManager = uiManager_.get();
if (methodName == "createNode") {
auto paramCount = 5;
return jsi::Function::createFromHostFunction(
runtime,
name,
paramCount,
[uiManager, methodName, paramCount](
jsi::Runtime& runtime,
const jsi::Value& /*thisValue*/,
const jsi::Value* arguments,
size_t count) -> jsi::Value {
try {
validateArgumentCount(runtime, methodName, paramCount, count);
auto instanceHandle =
instanceHandleFromValue(runtime, arguments[4], arguments[0]);
if (!instanceHandle) {
react_native_assert(false);
return jsi::Value::undefined();
}
// 把构造的ShadowNode封装成JSI::Vaule以便返回给JS层
return valueFromShadowNode(
runtime,
// 调用的uiManager->createNode来构造ShadowNode,详见1.8
uiManager->createNode(
tagFromValue(arguments[0]),
stringFromValue(runtime, arguments[1]),
surfaceIdFromValue(runtime, arguments[2]),
RawProps(runtime, arguments[3]),
std::move(instanceHandle)),
true);
} catch (const std::logic_error& ex) {
LOG(FATAL) << "logic_error in createNode: " << ex.what();
}
});
}
// ...
}
1.8 UIManager::createNode
这里就是真正构建shadowNode的地方,回过头去看一下Codegen生成的脚手架,会发现这个方法里用到的好多类在刚刚都见过。
componentDescriptor,Props,State,ShadowNode。
后面我们结合脚手架生成的代码来看看这些类的作用。
std::shared_ptr<ShadowNode> UIManager::createNode(
Tag tag,
const std::string& name,
SurfaceId surfaceId,
RawProps rawProps,
InstanceHandle::Shared instanceHandle) const {
SystraceSection s("UIManager::createNode", "componentName", name);
// 我们每一个Fabric控件都会有一个ComponentDescriptor,然后会根据组件的名称注册到componentDescriptorRegistry_中去
// 这里我们就可以通过组件名称获取ComponentDescriptor
// 我们一会会介绍,根据我们自定义的组件来看的话,这里最终获取的是RTNTestViewComponentDescriptor
auto& componentDescriptor = componentDescriptorRegistry_->at(name);
auto fallbackDescriptor =
componentDescriptorRegistry_->getFallbackComponentDescriptor();
PropsParserContext propsParserContext{surfaceId, *contextContainer_.get()};
auto family = componentDescriptor.createFamily(
{tag, surfaceId, std::move(instanceHandle)});
const auto props = componentDescriptor.cloneProps(
propsParserContext, nullptr, std::move(rawProps));
const auto state = componentDescriptor.createInitialState(props, family);
// 详见3.1
auto shadowNode = componentDescriptor.createShadowNode(
ShadowNodeFragment{
.props = fallbackDescriptor != nullptr &&
fallbackDescriptor->getComponentHandle() ==
componentDescriptor.getComponentHandle()
? componentDescriptor.cloneProps(
propsParserContext,
props,
RawProps(folly::dynamic::object("name", name)))
: props,
.children = ShadowNodeFragment::childrenPlaceholder(),
.state = state,
},
family);
if (delegate_ != nullptr) {
// 详见3.2
delegate_->uiManagerDidCreateShadowNode(*shadowNode);
}
if (leakChecker_) {
leakChecker_->uiManagerDidCreateShadowNodeFamily(family);
}
return shadowNode;
}
脚手架代码
我们先来看一下脚手架生成的代码,一会接着上面createNode。
我们先看看注册ComponentDescriptor的流程,在第一章启动流程中,介绍过application会调用getDefaultReactHost构造ReactHost。
2.1 getDefaultReactHost
我们这里只关注注册ComponentDescriptor流程,其他的之前介绍启动流程的时候介绍过了。
这里调用DefaultComponentsRegistry.register
@OptIn(UnstableReactNativeAPI::class)
@JvmStatic
public fun getDefaultReactHost(
context: Context,
packageList: List<ReactPackage>,
jsMainModulePath: String = "index",
jsBundleAssetPath: String = "index",
isHermesEnabled: Boolean = true,
useDevSupport: Boolean = ReactBuildConfig.DEBUG,
cxxReactPackageProviders: List<(ReactContext) -> CxxReactPackage> = emptyList(),
): ReactHost {
//...
val componentFactory = ComponentFactory()
// 详见2.2
DefaultComponentsRegistry.register(componentFactory)
// ...
}
2.2 DefaultComponentsRegistry.register
构造DefaultComponentsRegistry
public fun register(componentFactory: ComponentFactory): DefaultComponentsRegistry =
DefaultComponentsRegistry(componentFactory)
2.3 DefaultComponentsRegistry
构造的时候会调用initHybrid,initHybrid是一个native方法。
private val mHybridData: HybridData = initHybrid(componentFactory)
@DoNotStrip private external fun initHybrid(componentFactory: ComponentFactory): HybridData
2.4 initHybrid
jni::local_ref<DefaultComponentsRegistry::jhybriddata>
DefaultComponentsRegistry::initHybrid(
jni::alias_ref<jclass>,
ComponentFactory* delegate) {
auto instance = makeCxxInstance(delegate);
auto buildRegistryFunction =
[](const EventDispatcher::Weak& eventDispatcher,
const ContextContainer::Shared& contextContainer)
-> ComponentDescriptorRegistry::Shared {
ComponentDescriptorParameters params{
.eventDispatcher = eventDispatcher,
.contextContainer = contextContainer,
.flavor = nullptr};
// buildRegistryFunction会调用sharedProviderRegistry,详见2.5
auto registry = DefaultComponentsRegistry::sharedProviderRegistry()
->createComponentDescriptorRegistry(params);
auto& mutableRegistry = const_cast<ComponentDescriptorRegistry&>(*registry);
mutableRegistry.setFallbackComponentDescriptor(
std::make_shared<UnimplementedNativeViewComponentDescriptor>(params));
return registry;
};
delegate->buildRegistryFunction = buildRegistryFunction;
return instance;
}
2.5 buildRegistryFunction
std::shared_ptr<const ComponentDescriptorProviderRegistry>
DefaultComponentsRegistry::sharedProviderRegistry() {
// 这里注册的是RN的核心模块
auto providerRegistry = CoreComponentsRegistry::sharedProviderRegistry();
// 这里注册我们自定义的模块,详见2.6
if (DefaultComponentsRegistry::registerComponentDescriptorsFromEntryPoint) {
(DefaultComponentsRegistry::registerComponentDescriptorsFromEntryPoint)(
providerRegistry);
} else {
LOG(WARNING)
<< "Custom component descriptors were not configured from JNI_OnLoad";
}
return providerRegistry;
}
2.6 DefaultComponentsRegistry::registerComponentDescriptorsFromEntryPoint
这里的registerComponentDescriptorsFromEntryPoint是facebook::react::registerComponents
void registerComponents(
std::shared_ptr<const ComponentDescriptorProviderRegistry> registry) {
// ...
// 详见2.7
autolinking_registerProviders(registry);
}
2.7 autolinking_registerProviders
这里调用add来注册ComponentDescriptor
RTNTestViewComponentDescriptor是脚手架生成的,concreteComponentDescriptorProvider是一个模板方法,其中生成ComponentDescriptorProvider中constructor可以构造RTNTestViewComponentDescriptor
void autolinking_registerProviders(std::shared_ptr<ComponentDescriptorProviderRegistry const> providerRegistry) {
providerRegistry->add(concreteComponentDescriptorProvider<RTNTestViewComponentDescriptor>());
return;
}
2.8 ComponentDescriptorRegistry::add
这里调用constructor,会构造RTNTestViewComponentDescriptor,然后根据名字和句柄分别存储在两个map中。
void ComponentDescriptorRegistry::add(
ComponentDescriptorProvider componentDescriptorProvider) const {
std::unique_lock lock(mutex_);
auto componentDescriptor = componentDescriptorProvider.constructor(
{parameters_.eventDispatcher,
parameters_.contextContainer,
componentDescriptorProvider.flavor});
// ...
auto sharedComponentDescriptor = std::shared_ptr<const ComponentDescriptor>(
std::move(componentDescriptor));
_registryByHandle[componentDescriptorProvider.handle] =
sharedComponentDescriptor;
_registryByName[componentDescriptorProvider.name] = sharedComponentDescriptor;
}
2.9 RTNTestViewComponentDescriptor
RTNTestViewComponentDescriptor是一个ConcreteComponentDescriptor,ConcreteComponentDescriptor封装了组件的信息,包括shadowNode,state,prop等。
而RTNTestViewShadowNode则是一个ConcreteViewShadowNode模板类,里面会包含所RTNTestViewProps,RTNTestViewEventEmitter,RTNTestViewState,这样脚手架就实现了一个自定义Fabric组件然后关联组件自己的Props,State,EventEmitter。
using RTNTestViewComponentDescriptor = ConcreteComponentDescriptor<RTNTestViewShadowNode>;
using RTNTestViewShadowNode = ConcreteViewShadowNode<
RTNTestViewComponentName,
RTNTestViewProps,
RTNTestViewEventEmitter,
RTNTestViewState>;
接着第一节创建ShadowNode
3.1 RTNTestViewComponentDescriptor.createShadowNode
构建了一个RTNTestViewShadowNode
std::shared_ptr<ShadowNode> createShadowNode(
const ShadowNodeFragment& fragment,
const ShadowNodeFamily::Shared& family) const override {
// ShadowNodeT是模板参数,RTNTestViewShadowNode,所以这里构建了一个RTNTestViewShadowNode
auto shadowNode =
std::make_shared<ShadowNodeT>(fragment, family, getTraits());
adopt(*shadowNode);
return shadowNode;
}
3.2 uiManagerDidCreateShadowNode
这里也是接着1.8的,从delegate_->uiManagerDidCreateShadowNode过来。
void Scheduler::uiManagerDidCreateShadowNode(const ShadowNode& shadowNode) {
if (delegate_ != nullptr) {
// 详见3.3
delegate_->schedulerDidRequestPreliminaryViewAllocation(shadowNode);
}
}
3.3 FabricUIManagerBinding::schedulerDidRequestPreliminaryViewAllocation
调用了mountingManager调用maybePreallocateShadowNode,构造好的shadowNode后续需要mount挂载,挂载之后就会构建原生的View。
void FabricUIManagerBinding::schedulerDidRequestPreliminaryViewAllocation(
const ShadowNode& shadowNode) {
auto mountingManager = getMountingManager("preallocateView");
if (!mountingManager) {
return;
}
// 详见3.4
mountingManager->maybePreallocateShadowNode(shadowNode);
// ...
}
3.4 FabricMountingManager::maybePreallocateShadowNode
这里构建了ShadowView,然后调用了preallocateShadowView
void FabricMountingManager::maybePreallocateShadowNode(
const ShadowNode& shadowNode) {
if (!shadowNode.getTraits().check(ShadowNodeTraits::Trait::FormsView)) {
return;
}
static thread_local bool onMainThread = isOnMainThread();
if (onMainThread) {
// View preallocation is not beneficial when rendering on the main thread
return;
}
// 构造ShadowView
auto shadowView = ShadowView(shadowNode);
if (ReactNativeFeatureFlags::useOptimisedViewPreallocationOnAndroid()) {
std::lock_guard lock(preallocateMutex_);
preallocatedViewsQueue_.push_back(std::move(shadowView));
} else {
// 详见3.5
preallocateShadowView(shadowView);
}
}
3.5 FabricMountingManager::preallocateShadowView
每个surfaceId会映射一个队列,队列里会记录所有使用过的View的TAG,然后调用preallocateView,preallocateView映射java层的方法。
void FabricMountingManager::preallocateShadowView(
const ShadowView& shadowView) {
SystraceSection section("FabricMountingManager::preallocateShadowView");
{
// 每个SurfaceId会映射一个数组,数组里记录使用到的View的TAG
std::lock_guard lock(allocatedViewsMutex_);
auto allocatedViewsIterator =
allocatedViewRegistry_.find(shadowView.surfaceId);
if (allocatedViewsIterator == allocatedViewRegistry_.end()) {
return;
}
auto& allocatedViews = allocatedViewsIterator->second;
if (allocatedViews.find(shadowView.tag) != allocatedViews.end()) {
return;
}
allocatedViews.insert(shadowView.tag);
}
bool isLayoutableShadowNode = shadowView.layoutMetrics != EmptyLayoutMetrics;
// 映射java的方法,preallocateView
static auto preallocateView =
JFabricUIManager::javaClassStatic()
->getMethod<void(jint, jint, jstring, jobject, jobject, jboolean)>(
"preallocateView");
// ...处理Prop和State
auto component = getPlatformComponentName(shadowView);
// 调用preallocateView,这里会调用到java的preallocateView,详见3.6
preallocateView(
javaUIManager_,
shadowView.surfaceId,
shadowView.tag,
component.get(),
props.get(),
(javaStateWrapper != nullptr ? javaStateWrapper.get() : nullptr),
isLayoutableShadowNode);
}
3.6 SurfaceMountingManager.preallocateView
调用createViewUnsafe构建View
@UiThread
public void preallocateView(
@NonNull String componentName,
int reactTag,
@Nullable ReadableMap props,
@Nullable StateWrapper stateWrapper,
boolean isLayoutable) {
UiThreadUtil.assertOnUiThread();
if (isStopped()) {
return;
}
if (getNullableViewState(reactTag) != null) {
return;
}
// 详见3.7
createViewUnsafe(componentName, reactTag, props, stateWrapper, null, isLayoutable);
}
3.7 createViewUnsafe
@UiThread
public void createViewUnsafe(
@NonNull String componentName,
int reactTag,
@Nullable ReadableMap props,
@Nullable StateWrapper stateWrapper,
@Nullable EventEmitterWrapper eventEmitterWrapper,
boolean isLayoutable) {
Systrace.beginSection(
Systrace.TRACE_TAG_REACT_JAVA_BRIDGE,
"SurfaceMountingManager::createViewUnsafe(" + componentName + ")");
try {
ReactStylesDiffMap propMap = new ReactStylesDiffMap(props);
// 将View的核心要素Prop,State,EventEmitter封装到ViewState
ViewState viewState = new ViewState(reactTag);
viewState.mCurrentProps = propMap;
viewState.mStateWrapper = stateWrapper;
viewState.mEventEmitter = eventEmitterWrapper;
mTagToViewState.put(reactTag, viewState);
if (isLayoutable) {
ViewManager viewManager = mViewManagerRegistry.get(componentName);
// 调用ViewManager.createView,这里的ViewManager每个Fabric组件都有一个
// 以我们实现的RTNTestViewManager为例来看看,详见3.8
viewState.mView =
viewManager.createView(
reactTag, mThemedReactContext, propMap, stateWrapper, mJSResponderHandler);
viewState.mViewManager = viewManager;
}
} finally {
Systrace.endSection(Systrace.TRACE_TAG_REACT_JAVA_BRIDGE);
}
}
3.8 RTNTestViewManager
这里我们实现的RTNTestViewManager继承自SimpleViewManager,而SimpleViewManager继承自BaseViewManager,BaseViewManager继承自ViewManager。
ViewManager的createView会调用createViewInstance,同时createView会更新Prop,State,EventEmitter。
而这里createViewInstance就会构建View。
@ReactModule(name = RTNTestViewManager.NAME)
public class RTNTestViewManager extends SimpleViewManager<TextView>
implements RTNTestViewManagerInterface<TextView> {
private final ViewManagerDelegate<TextView> mDelegate;
static final String NAME = "RTNTestView";
public RTNTestViewManager(ReactApplicationContext context) {
mDelegate = new RTNTestViewManagerDelegate<>(this);
}
@Nullable
@Override
protected ViewManagerDelegate<TextView> getDelegate() {
return mDelegate;
}
@NonNull
@Override
public String getName() {
return RTNTestViewManager.NAME;
}
@NonNull
@Override
protected TextView createViewInstance(@NonNull ThemedReactContext context) {
// 返回自定义的View,这里只是随便返回一个TextView,实际是要返回一个自定义的View
return new TextView(context);
}
@Override
@ReactProp(name = "text")
public void setText(TextView view, @Nullable String text) {
view.setText(text);
}
}
其他
-
Props
Props继承了ViewProps,之所以要有继承是因为需要实现一些基础的属性,ViewProps本质是BaseViewProps,BaseViewProps继承了YogaStylableProps和AccessibilityProps,实现基础属性,比如有宽度高度等等基础属性,这样我们自定义的Fabric就只需要定义我们额外的属性。class RTNTestViewProps final : public ViewProps {
public:
RTNTestViewProps() = default;
RTNTestViewProps(const PropsParserContext& context, const RTNTestViewProps &sourceProps, const RawProps &rawProps);#pragma mark - Props std::string text{};
};
小结
本节我们只是介绍了Fabric的组件以及渲染器的核心流程,在JS层定义UI布局,然后React层会构建一个DOM树,后面会将DOM树同步到ShadowNode层,最后会根据ShadowNode构建原生组件。
EmitterEvent,Props,State这些分发设置我们就不继续深入研究了,如果后续有机会的话可能会更加深入学习,目前我们只是了解一下跨端开发的原理和设计思想,拓宽一下眼界,下一节我们会学习一下Flutter,Flutter和RN的设计思想完全不同。