通过ReactNative viewTag获取原生的View

原文:http://blog.fiftykg.com/font_end/react_native/通过ReactNative-viewTag获取原生的View.html

前言

前端的同学希望传一个reactTag(rootViewTag/viewTag)给Android原生,让原生找到对应的View进行一些黑科技的操作。

然后问题来了,ReactNative的reactTag虽然是一个int值,但是与Activity#findViewByIdid不是同一个东西!

分析

1、ReactNative提供给Android原生操作UI的Module就是UIManagerModule,代码搜索viewTag,可以看到以下类似方法,表明通过viewTag操作view的逻辑在mUIImplementation中。

@ReactMethod
public void removeRootView(int rootViewTag) {
mUIImplementation.removeRootView(rootViewTag);
}

public void updateNodeSize(int nodeViewTag, int newWidth, int newHeight) {
getReactApplicationContext().assertOnNativeModulesQueueThread();

mUIImplementation.updateNodeSize(nodeViewTag, newWidth, newHeight);
}

2、再看UIImplementation,搜索viewTag,可以看到操作的逻辑在mShadowNodeRegistrymReactShadowNode,ShadowNodeRegistry是ReactShadowNode与tag的逻辑,所以继续看ReactShadowNode。搜索tag相关,可以发现一个很可疑的类NativeViewHierarchyManager!
看类的注释,NativeViewHierarchyManager处理了原生View与ReactNative ViewManager之间的映射关系。
看方法,resolveView入参是一个tag,返回是一个View,应该就是这个了!最终测试发现也是如此。
剩下的就看操作了!

操作

没错,就是反射了。

public static View getViewByTag(ReactContext reactContext, int viewTag) {
NativeViewHierarchyManager manager = getNativeViewHierarchyManager(reactContext);
if (manager == null) {
return null;
}
return manager.resolveView(viewTag);
}

public static NativeViewHierarchyManager getNativeViewHierarchyManager(
ReactContext reactContext) {
try {
// 获取 UIImplementation
UIManagerModule uiManager = reactContext.getNativeModule(UIManagerModule.class);
UIImplementation uiImplementation = uiManager.getUIImplementation();
// 获取 UIImplementation#mOperationsQueue
Field mOperationsQueueField = uiImplementation.getClass()
.getDeclaredField("mOperationsQueue");
mOperationsQueueField.setAccessible(true);
UIViewOperationQueue uiViewOperationQueue = (UIViewOperationQueue) mOperationsQueueField
.get(uiImplementation);
// 获取 UIViewOperationQueue#NativeViewHierarchyManager
Field mNativeViewHierarchyManagerField = UIViewOperationQueue.class
.getDeclaredField("mNativeViewHierarchyManager");
mNativeViewHierarchyManagerField.setAccessible(true);
NativeViewHierarchyManager mNativeViewHierarchyManager = (NativeViewHierarchyManager) mNativeViewHierarchyManagerField
.get(uiViewOperationQueue);
return mNativeViewHierarchyManager;
} catch (NoSuchFieldException e) {
e.printStackTrace();
return null;
} catch (IllegalAccessException e) {
e.printStackTrace();
return null;
}
}

你可能感兴趣的:(ReactNative)