Android React-Native通信數(shù)據(jù)模型分析
無(wú)論是計(jì)算機(jī)領(lǐng)域還是日常生活中,我們所言的通信,其核心都是數(shù)據(jù)信息的交換,而數(shù)據(jù)模型的優(yōu)劣對(duì)通信效率有著決定性的作用。
在React-Native項(xiàng)目中,Javascript語(yǔ)言與Native兩種語(yǔ)言(Java或OC等)間存在著大量的數(shù)據(jù)交換,也就是所謂的通信。眾所周知,移動(dòng)APP對(duì)性能的要求無(wú)比苛刻,如果通信數(shù)據(jù)模型設(shè)計(jì)地不合理,很可能引起多線程下的數(shù)據(jù)安全問題,以及應(yīng)用性能問題,比如內(nèi)存泄漏,UI繪制緩慢等。
前面幾篇博客我們?cè)敿?xì)分析過(guò)React-Native的通信機(jī)制,主要有兩個(gè)方向: Java->Bridge->Javascript和Javascript->Bridge->Java。所以,真正的數(shù)據(jù)交換其實(shí)發(fā)生在Java與Bridge,Javascript與Bridge兩個(gè)環(huán)節(jié)。
Javascript與Bridge間的數(shù)據(jù)通信是借助于Webkit使用Json完成,簡(jiǎn)單實(shí)用,水到渠成,不多分析。而Java與Bridge間的數(shù)據(jù)通信相比之下就復(fù)雜多了,作為真正運(yùn)行在設(shè)備上的程序語(yǔ)言,這恰恰是決定整個(gè)通信過(guò)程效率高低最核心的一環(huán),也是本篇博客研究的內(nèi)容。
Java是Android應(yīng)用程序的本地開發(fā)語(yǔ)言,而Bridge是使用C++開發(fā)的動(dòng)態(tài)鏈接庫(kù),由Java語(yǔ)言通過(guò)JNI的方式調(diào)用。Java與Bridge間的數(shù)據(jù)通信,實(shí)質(zhì)是Java和C++兩種程序語(yǔ)言間的數(shù)據(jù)傳輸,而傳遞的方向又分為兩個(gè)場(chǎng)景:Java傳輸數(shù)據(jù)給C++ 和C++ 傳輸數(shù)據(jù)給Java。
我們先來(lái)看第一種場(chǎng)景。
Java主動(dòng)向Javascript通信,主要是通過(guò)ReactBridge.java類的callFunction方法,將需要調(diào)用的組件(moduleId)、功能(methodId)、數(shù)據(jù)(arguments)三者傳遞到Bridge。
package com.facebook.react.bridge; public class ReactBridge extends Countable { static final String REACT_NATIVE_LIB = "reactnativejni"; static { SoLoader.loadLibrary(REACT_NATIVE_LIB); } ... public native void callFunction(int moduleId, int methodId, NativeArray arguments); ... }
我們可以看到,傳輸?shù)臄?shù)據(jù)類型是NativeArray,來(lái)瞧下具體的代碼,位于com.facebook.react.bridge包下:
public abstract class NativeArray { static { SoLoader.loadLibrary(ReactBridge.REACT_NATIVE_LIB); } protected NativeArray(HybridData hybridData) { mHybridData = hybridData; } @Override public native String toString(); @DoNotStrip private HybridData mHybridData; }
NativeArray是一個(gè)抽象類,其中,只有一個(gè)HybridData類型成員變量,由其構(gòu)造方法賦值初始化。
NativeArray還有一個(gè)名為ReadableNativeArray的直接子類,和一個(gè)名為WritableNativeArray的間接子類,后者是繼承于前者。顧名思義,一個(gè)是用于讀數(shù)據(jù),一個(gè)是用于寫數(shù)據(jù)。
Java向Bridge傳輸數(shù)據(jù),自然就是寫數(shù)據(jù)了,所以我們先來(lái)看WritableNativeArray。
package com.facebook.react.bridge; public class WritableNativeArray extends ReadableNativeArray implements WritableArray { static { SoLoader.loadLibrary(ReactBridge.REACT_NATIVE_LIB); } public WritableNativeArray() { super(initHybrid()); } @Override public native void pushNull(); @Override public native void pushBoolean(boolean value); @Override public native void pushDouble(double value); @Override public native void pushInt(int value); @Override public native void pushString(String value); @Override public void pushArray(WritableArray array) { Assertions.assertCondition( array == null || array instanceof WritableNativeArray, "Illegal type provided"); pushNativeArray((WritableNativeArray) array); } @Override public void pushMap(WritableMap map) { Assertions.assertCondition( map == null || map instanceof WritableNativeMap, "Illegal type provided"); pushNativeMap((WritableNativeMap) map); } private native static HybridData initHybrid(); private native void pushNativeArray(WritableNativeArray array); private native void pushNativeMap(WritableNativeMap map); }
里面有7個(gè)寫數(shù)據(jù)的native方法,涵蓋了int、string,array,map等不同的數(shù)據(jù)類型和結(jié)構(gòu)。
還有一個(gè)名為initHybrid()的native方法,用于創(chuàng)建HybridData類的實(shí)例,然后通過(guò)構(gòu)造方法給其超父類NativeArray的mHybridData成員變量賦值,具體作用后面來(lái)分析,先略過(guò)。
接下來(lái),我們來(lái)驗(yàn)證一下WritableNativeArray是否是真正傳輸給Bridge的數(shù)據(jù)類型。
Java調(diào)用Javascript組件,都是由名為JavaScriptModuleInvocationHandler的動(dòng)態(tài)代理類統(tǒng)一攔截處理的嗎?來(lái)回顧一下代碼,位于com.facebook.react.bridge.JavaScriptModuleRegistry.java:
private static class JavaScriptModuleInvocationHandler implements InvocationHandler { private final CatalystInstanceImpl mCatalystInstance; private final JavaScriptModuleRegistration mModuleRegistration; public JavaScriptModuleInvocationHandler( CatalystInstanceImpl catalystInstance, JavaScriptModuleRegistration moduleRegistration) { mCatalystInstance = catalystInstance; mModuleRegistration = moduleRegistration; } @Override public @Nullable Object invoke(Object proxy, Method method, Object[] args) throws Throwable { String tracingName = mModuleRegistration.getTracingName(method); mCatalystInstance.callFunction( mModuleRegistration.getModuleId(), mModuleRegistration.getMethodId(method), Arguments.fromJavaArgs(args), tracingName); return null; } }
callFunction方法傳遞的參數(shù)類型是Arguments.fromJavaArgs(args),具體代碼又如下:
public static WritableNativeArray fromJavaArgs(Object[] args) { WritableNativeArray arguments = new WritableNativeArray(); for (int i = 0; i < args.length; i++) { Object argument = args[i]; if (argument == null) { arguments.pushNull(); continue; } Class argumentClass = argument.getClass(); if (argumentClass == Boolean.class) { arguments.pushBoolean(((Boolean) argument).booleanValue()); } else if (argumentClass == Integer.class) { arguments.pushDouble(((Integer) argument).doubleValue()); } else if (argumentClass == Double.class) { arguments.pushDouble(((Double) argument).doubleValue()); } else if (argumentClass == Float.class) { arguments.pushDouble(((Float) argument).doubleValue()); } else if (argumentClass == String.class) { arguments.pushString(argument.toString()); } else if (argumentClass == WritableNativeMap.class) { arguments.pushMap((WritableNativeMap) argument); } else if (argumentClass == WritableNativeArray.class) { arguments.pushArray((WritableNativeArray) argument); } else { throw new RuntimeException("Cannot convert argument of type " + argumentClass); } } return arguments; }
正如我們猜測(cè)的一般,fromJavaArgs靜態(tài)方法返回的是一個(gè)新創(chuàng)建的WritableNativeArray對(duì)象實(shí)例,然后按照數(shù)據(jù)類型,調(diào)用相應(yīng)的push方法。有些特殊的是,int型和float型都當(dāng)成了double型來(lái)處理,這樣做并不會(huì)造成數(shù)據(jù)的損害。
剛剛說(shuō)到,WritableNativeArray的所有寫入數(shù)據(jù)的方法都是native方法,即Java層面的通信數(shù)據(jù)全部是直接寫入到Bridge層的,換言之,WritableNativeArray僅僅起到了數(shù)據(jù)傳輸管道的作用。這樣做,有兩個(gè)好處:
1、數(shù)據(jù)只在C++存有一份,這樣避免了數(shù)據(jù)具有多個(gè)副本,節(jié)省了一部分的內(nèi)存。
2、減小對(duì)WritableNativeArray對(duì)象的依賴,使其容易釋放,可以由虛擬機(jī)GC自動(dòng)回收內(nèi)存。
那么,在Bridge層中,C++又是如何處理push過(guò)來(lái)的數(shù)據(jù)的呢?
先來(lái)看一下WritableNativeArray中native方法在JNI中動(dòng)態(tài)注冊(cè)的代碼,位于react/jni/OnLoad.cpp中:
static void registerNatives() { jni::registerNatives("com/facebook/react/bridge/WritableNativeArray", { makeNativeMethod("initHybrid", WritableNativeArray::initHybrid), makeNativeMethod("pushNull", WritableNativeArray::pushNull), makeNativeMethod("pushBoolean", WritableNativeArray::pushBoolean), makeNativeMethod("pushDouble", WritableNativeArray::pushDouble), makeNativeMethod("pushInt", WritableNativeArray::pushInt), makeNativeMethod("pushString", WritableNativeArray::pushString), makeNativeMethod("pushNativeArray", WritableNativeArray::pushNativeArray), makeNativeMethod("pushNativeMap", "(Lcom/facebook/react/bridge/WritableNativeMap;)V", WritableNativeArray::pushNativeMap), }); }
很明顯,在C++中也存在著一個(gè)名為WritableNativeArray的類,具有與著native方法相對(duì)應(yīng)的方法,巧的是,它也是繼承于ReadableNativeArray類(注意HybridClass模板類的第二個(gè)泛型表示父類):
struct WritableNativeArray : public jni::HybridClass<WritableNativeArray, ReadableNativeArray> { static constexpr const char* kJavaDescriptor = "Lcom/facebook/react/bridge/WritableNativeArray;"; WritableNativeArray() : HybridBase(folly::dynamic({})) {} static local_ref<jhybriddata> initHybrid(alias_ref<jclass>) { return makeCxxInstance(); } void pushNull() { ... array.push_back(nullptr); } void pushBoolean(jboolean value) { ... array.push_back(value == JNI_TRUE); } void pushDouble(jdouble value) { ... array.push_back(value); } void pushInt(jint value) { ... array.push_back(value); } void pushString(jstring value) { ... array.push_back(wrap_alias(value)->toStdString()); } void pushNativeArray(WritableNativeArray* otherArray) { ... array.push_back(std::move(otherArray->array)); otherArray->isConsumed = true; } void pushNativeMap(jobject jmap) { ... array.push_back(std::move(map->map)); map->isConsumed = true; } ... }
看到這里,我們不禁會(huì)猜測(cè),C++中的ReadableNativeArray類很可能也是繼承于NativeArray。
當(dāng)然,事實(shí)確實(shí)是這樣的。在C++中存在著與Java中完全呼應(yīng)的三個(gè)類:NativeArray、ReadableNativeArray、WritableNativeArray,命名和繼承關(guān)系都是完全一致的!
而且可以看到,所有的數(shù)據(jù)都被存儲(chǔ)到父類NativeArray的array變量中。
不過(guò),問題來(lái)了!
C++中的WritableNativeArray對(duì)象和Java中的WritableNativeArray兩個(gè)同名對(duì)象間是否存在著某種聯(lián)系呢,比如一一映射的關(guān)系?
答案是肯定的! 因?yàn)槊慨?dāng)一個(gè)Java層的WritableNativeArray對(duì)象被創(chuàng)建,在C++層都會(huì)有一個(gè)相應(yīng)的WritableNativeArray對(duì)象被創(chuàng)建,用來(lái)接收J(rèn)ava層push過(guò)來(lái)的數(shù)據(jù)。
再來(lái)回顧下WritableNativeArray.java創(chuàng)建的過(guò)程。
public class WritableNativeArray extends ReadableNativeArray implements WritableArray { ... public WritableNativeArray() { super(initHybrid()); } ... private native static HybridData initHybrid(); ... }
在構(gòu)造WritableNativeArray的時(shí)候,會(huì)通過(guò)initHybrid方法創(chuàng)建一個(gè)HybridData對(duì)象,并保存到其超父類NativeArray的成員變量mHybridData中。
而HybridData對(duì)象又是什么呢?
public class HybridData { // Private C++ instance private long mNativePointer = 0; public HybridData() { Prerequisites.ensure(); } public native void resetNative(); protected void finalize() throws Throwable { resetNative(); super.finalize(); } }
public class Prerequisites { ... public static void ensure() { SoLoader.loadLibrary("fbjni"); } ... }
構(gòu)造函數(shù)中Prerequisites.ensure(),是用來(lái)加載fbjni動(dòng)態(tài)鏈接庫(kù)的。
在HybridData 類中,有一個(gè)long的私有成員變量,根據(jù)注釋和名字可以猜測(cè)與C++指針相關(guān),具體是不是這樣呢?我們來(lái)看HybridData對(duì)象通過(guò)initHybrid()初始化的過(guò)程。
代碼位于react/jni/OnLoad.cpp中:
struct WritableNativeArray : public jni::HybridClass<WritableNativeArray, ReadableNativeArray> { ... static local_ref<jhybriddata> initHybrid(alias_ref<jclass>) { return makeCxxInstance(); } ... }
這里的jhybriddata指的就是HybridData(Java)對(duì)象,其是通過(guò)typedef方式定義在jni/first-party/jni/fbjni/Hybrid.h中的。
... struct HybridData : public JavaClass<HybridData> { constexpr static auto kJavaDescriptor = "Lcom/facebook/jni/HybridData;"; void setNativePointer(std::unique_ptr<BaseHybridClass> new_value); BaseHybridClass* getNativePointer(); static local_ref<HybridData> create(); }; ... typedef detail::HybridData::javaobject jhybriddata; ...
facebook在這里對(duì)在JNI中創(chuàng)建Java對(duì)象的過(guò)程做了非常高效的封裝,即JavaClass對(duì)象。所有JavaClass的子類都通過(guò)一個(gè)名為kJavaDescriptor的字符串指針,來(lái)描述相對(duì)應(yīng)的Java對(duì)象類名。
繼續(xù)來(lái)看makeCxxInstance()是如何創(chuàng)建HybridData(Java) 對(duì)象的。代碼同樣在jni/first-party/jni/fbjni/Hybrid.h中。
class HybridClass : public detail::HybridTraits<Base>::CxxBase { ... static local_ref<detail::HybridData> makeHybridData(std::unique_ptr<T> cxxPart) { auto hybridData = detail::HybridData::create(); hybridData->setNativePointer(std::move(cxxPart)); return hybridData; } template <typename... Args> static local_ref<detail::HybridData> makeCxxInstance(Args&&... args) { return makeHybridData(std::unique_ptr<T>(new T(std::forward<Args>(args)...))); } ... }
結(jié)合下前面的WritableNativeArray(C++)來(lái)看
struct WritableNativeArray : public jni::HybridClass<WritableNativeArray, ReadableNativeArray> { static constexpr const char* kJavaDescriptor = "Lcom/facebook/react/bridge/WritableNativeArray;"; ... static local_ref<jhybriddata> initHybrid(alias_ref<jclass>) { return makeCxxInstance(); } ... }
在創(chuàng)建HybridData(Java)的時(shí)候,模板類HybridClass的第一個(gè)泛型T,表示的是WritableNativeArray(C++)這個(gè)結(jié)構(gòu)體。所以,makeHybridData中的new T(std::forward(args)…)新創(chuàng)建的T就是WritableNativeArray(C++)對(duì)象。
繼續(xù)來(lái)看makeHybridData方法,參數(shù)cxxPart是剛剛創(chuàng)建的WritableNativeArray對(duì)象的指針。里面通過(guò)detail::HybridData::create()真正創(chuàng)建了HybridData(Java)和HybridData(C++)對(duì)象,并將WritableNativeArray(C++)對(duì)象的指針通過(guò)setNativePointer方法注入到了HybridData(Java)中。
接下來(lái),看create和setNativePointer兩個(gè)方法的細(xì)節(jié),在Hybrid.cpp中:
local_ref<HybridData> HybridData::create() { return newInstance(); }
void HybridData::setNativePointer(std::unique_ptr<basehybridclass> new_value) { static auto pointerField = getClass()->getField<jlong>("mNativePointer"); auto* old_value = reinterpret_cast<BaseHybridClass*>(getFieldValue(pointerField)); if (new_value) { ... } else if (old_value == 0) { return; } delete old_value; ... setFieldValue(pointerField, reinterpret_cast<jlong>(new_value.release())); }
create里面是通過(guò)newInstance方式創(chuàng)建了HybridData(Java) 和HybridData(C++)對(duì)象,具體細(xì)節(jié)不細(xì)說(shuō)了,讀者自行去研究facebook的封裝。
HybridData(C++)的setNativePointer方法中的參數(shù)new_value,為WritableNativeArray(C++)對(duì)象的指針, 使用reinterpret_cast關(guān)鍵字將其轉(zhuǎn)換成long型,設(shè)置到mNativePointer中。而這里的mNativePointer,就是我們前面談到的HybridData(Java)類的成員變量了!
有一點(diǎn)需要注意的是,保存WritableNativeArray(C++)對(duì)象指針的時(shí)候,會(huì)先獲取原先保存的指針并刪除回收(如果存在的話),主要目的是回收WritableNativeArray(C++)對(duì)象的內(nèi)存,調(diào)用的時(shí)機(jī)是HybridData(Java)的finalize,也就是WritableNativeArray(Java)和HybridData(Java)被虛擬機(jī)GC回收的時(shí)候,這說(shuō)明了一點(diǎn),就是WritableNativeArray(C++)對(duì)象實(shí)例和WritableNativeArray(Java)對(duì)象實(shí)例的內(nèi)存釋放是完全同步的,都是交由Java GC來(lái)觸發(fā)!
到這里我們稍稍梳理一下。
當(dāng)WritableNativeArray(Java)創(chuàng)建的時(shí)候,通過(guò)JNI調(diào)用會(huì)先創(chuàng)建WritableNativeArray(C++)對(duì)象,其后會(huì)創(chuàng)建HybridData(Java)和HybridData(C++),同時(shí)將WritableNativeArray(C++)的指針保存到HybridData(Java)的mNativePointer成員變量中,最后把HybridData(Java)保存到WritableNativeArray(Java)對(duì)象里面。
這樣設(shè)計(jì)有一個(gè)好處。當(dāng)WritableNativeArray(Java)通過(guò)JNI的方式傳遞到C++層時(shí),可以通過(guò)保存在其內(nèi)部的HybridData(Java)對(duì)象的mNativePointer的值,還原WritableNativeArray(C++)對(duì)象。
這個(gè)還原過(guò)程是通過(guò)內(nèi)聯(lián)函數(shù)cthis函數(shù)實(shí)現(xiàn)的,代碼在jni/first-party/jni/fbjni/Hybrid.h中:
// Given a *_ref object which refers to a hybrid class, this will reach inside // of it, find the mHybridData, extract the C++ instance pointer, cast it to // the appropriate type, and return it. template <typename T> inline auto cthis(T jthis) -> decltype(jthis->cthis()) { return jthis->cthis(); }
inline T* HybridClass<T, B>::JavaPart::cthis() { static auto field = HybridClass<T, B>::JavaPart::javaClassStatic()->template getField<detail::HybridData::javaobject>("mHybridData"); auto hybridData = this->getFieldValue(field); ... // I'd like to use dynamic_cast here, but -fno-rtti is the default. T* value = static_cast<T*>(hybridData->getNativePointer()); ... return value; };
BaseHybridClass* HybridData::getNativePointer() { static auto pointerField = getClass()->getField<jlong>("mNativePointer"); auto* value = reinterpret_cast<BaseHybridClass*>(getFieldValue(pointerField)); ... return value; }
先提取出WritableNativeArray(Java)對(duì)象的mHybridData,再提取其mNativePointer,最后使用reinterpret_cast還原出WritableNativeArray(C++)對(duì)象。而在WritableNativeArray(C++)對(duì)象中存儲(chǔ)著所有push的數(shù)據(jù)(定義在其父類NativeArray中),這樣數(shù)據(jù)的提取工作就完成了。
到此,Java傳輸數(shù)據(jù)給C++的場(chǎng)景分析完成,下面我們來(lái)研究反向過(guò)程。
C++傳輸數(shù)據(jù)給Java的場(chǎng)景,主要是在callNativeModules里面,我們直接來(lái)看makeJavaCall方法,在jni\react\jni\OnLoad.cpp中
static void makeJavaCall(JNIEnv* env, ExecutorToken executorToken, jobject callback, const MethodCall& call) { if (call.arguments.isNull()) { return; } ... auto newArray = ReadableNativeArray::newObjectCxxArgs(std::move(call.arguments)); env->CallVoidMethod( callback, gCallbackMethod, static_cast<JExecutorTokenHolder*>(executorToken.getPlatformExecutorToken().get())->getJobj(), call.moduleId, call.methodId, newArray.get()); }
call.arguments是一個(gè)封裝好的folly::dynamic對(duì)象(詳見folly開源庫(kù)),通過(guò)newObjectCxxArgs方法轉(zhuǎn)換成ReadableNativeArray(C++)對(duì)象,實(shí)現(xiàn)在jni/first-party/jni/fbjni/Hybrid.h中:
template <typename... Args> static local_ref<JavaPart> newObjectCxxArgs(Args&&... args) { auto hybridData = makeCxxInstance(std::forward<Args>(args)...); return JavaPart::newInstance(hybridData); }
template <typename... Args> static local_ref<detail::HybridData> makeCxxInstance(Args&&... args) { return makeHybridData(std::unique_ptr<T>(new T(std::forward<Args>(args)...))); }
template<typename JC, typename... Args> static local_ref<JC> newInstance(Args... args) { static auto cls = JC::javaClassStatic(); static auto constructor = cls->template getConstructor<typename JC::javaobject(Args...)>(); return cls->newObject(constructor, args...); }
創(chuàng)建ReadableNativeArray(C++)對(duì)象的過(guò)程和前面創(chuàng)建WritableNativeArray(C++)對(duì)象的過(guò)程一模一樣。先創(chuàng)建HybridData(Java)和HybridData(C++),同時(shí)將ReadableNativeArray(C++)的指針保存到HybridData(Java)的mNativePointer成員變量中。最后ReadableNativeArray(Java)對(duì)象被封裝在JavaPart中(再次用到facebook用JNI創(chuàng)建Java對(duì)象的封裝庫(kù)),通過(guò)get方法獲取到真正的實(shí)例。
繼續(xù)來(lái)看ReadableNativeArray(Java),位于包c(diǎn)om.facebook.react.bridge中:
public class ReadableNativeArray extends NativeArray implements ReadableArray { static { SoLoader.loadLibrary(ReactBridge.REACT_NATIVE_LIB); } protected ReadableNativeArray(HybridData hybridData) { super(hybridData); } @Override public native int size(); @Override public native boolean isNull(int index); @Override public native boolean getBoolean(int index); @Override public native double getDouble(int index); @Override public native int getInt(int index); @Override public native String getString(int index); @Override public native ReadableNativeArray getArray(int index); @Override public native ReadableNativeMap getMap(int index); @Override public native ReadableType getType(int index); }
ReadableNativeArray(Java)同樣也是一個(gè)管道,所有數(shù)據(jù)仍然是存在C++層,必須全部通過(guò)native本地方法來(lái)提取,依賴具有了前面說(shuō)到的兩個(gè)優(yōu)點(diǎn):減少內(nèi)存和容易回收。
ReadableNativeArray::ReadableNativeArray(folly::dynamic array) : HybridBase(std::move(array)) {} ... jint ReadableNativeArray::getSize() { return array.size(); } jboolean ReadableNativeArray::isNull(jint index) { return array.at(index).isNull() ? JNI_TRUE : JNI_FALSE; } jboolean ReadableNativeArray::getBoolean(jint index) { return array.at(index).getBool() ? JNI_TRUE : JNI_FALSE; } jdouble ReadableNativeArray::getDouble(jint index) { const folly::dynamic& val = array.at(index); if (val.isInt()) { return val.getInt(); } return val.getDouble(); } jint ReadableNativeArray::getInt(jint index) { auto integer = array.at(index).getInt(); ... jint javaint = static_cast<jint>(integer); ... return javaint; } const char* ReadableNativeArray::getString(jint index) { const folly::dynamic& dyn = array.at(index); if (dyn.isNull()) { return nullptr; } return dyn.getString().c_str(); } ReadableNativeArray::getArray(jint index) { auto& elem = array.at(index); if (elem.isNull()) { return jni::local_ref<ReadableNativeArray::jhybridobject>(nullptr); } else { return ReadableNativeArray::newObjectCxxArgs(elem); } } jobject ReadableNativeArray::getMap(jint index) { return createReadableNativeMapWithContents(Environment::current(), array.at(index)); } jobject ReadableNativeArray::getType(jint index) { return type::getType(array.at(index).type()); } void ReadableNativeArray::registerNatives() { jni::registerNatives("com/facebook/react/bridge/ReadableNativeArray", { makeNativeMethod("size", ReadableNativeArray::getSize), makeNativeMethod("isNull", ReadableNativeArray::isNull), makeNativeMethod("getBoolean", ReadableNativeArray::getBoolean), makeNativeMethod("getDouble", ReadableNativeArray::getDouble), makeNativeMethod("getInt", ReadableNativeArray::getInt), makeNativeMethod("getString", ReadableNativeArray::getString), makeNativeMethod("getArray", ReadableNativeArray::getArray), makeNativeMethod("getMap", "(I)Lcom/facebook/react/bridge/ReadableNativeMap;", ReadableNativeArray::getMap), makeNativeMethod("getType", "(I)Lcom/facebook/react/bridge/ReadableType;", ReadableNativeArray::getType), }); }
對(duì)數(shù)據(jù)的提取,最后仍然是對(duì)array對(duì)象操作,其是定義在父類NativeArray.h中的,不在贅述。
整個(gè)數(shù)據(jù)模型的分析就到此結(jié)束了,總結(jié)一下有以下幾個(gè)特點(diǎn):
1、數(shù)據(jù)只有一份存儲(chǔ),即在C++中,無(wú)論是ReadableNativeArray(Java)還是WritableNativeArray(Java)都只是數(shù)據(jù)存取的管道。
2、ReadableNativeArray和WritableNativeArray在Java層和C++層又都有各自的實(shí)例,通過(guò)Java層實(shí)例的HybridData的mNativePointer作為紐帶鏈接,其存儲(chǔ)的是C++層實(shí)例的指針。
3、無(wú)論是Java層還是C++層的ReadableNativeArray和WritableNativeArray都是統(tǒng)一由Java GC進(jìn)行回收管理。
感謝閱讀,希望能幫助到大家,謝謝大家對(duì)本站的支持!
- react-native android狀態(tài)欄的實(shí)現(xiàn)
- React-native橋接Android原生開發(fā)詳解
- React-Native之Android(6.0及以上)權(quán)限申請(qǐng)?jiān)斀?/a>
- React-Native實(shí)現(xiàn)ListView組件之上拉刷新實(shí)例(iOS和Android通用)
- react-native 封裝選擇彈出框示例(試用ios&android)
- React-Native Android 與 IOS App使用一份代碼實(shí)現(xiàn)方法
- android中使用react-native設(shè)置應(yīng)用啟動(dòng)頁(yè)過(guò)程詳解
相關(guān)文章
Android實(shí)現(xiàn)網(wǎng)絡(luò)圖片瀏覽器
這篇文章主要為大家詳細(xì)介紹了Android實(shí)現(xiàn)網(wǎng)絡(luò)圖片瀏覽器的相關(guān)資料,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-05-05Android開發(fā)TextView內(nèi)的文字實(shí)現(xiàn)自動(dòng)換行
這篇文章主要為大家介紹了Android開發(fā)TextView內(nèi)的文字實(shí)現(xiàn)自動(dòng)換行,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-06-06Android中Volley框架進(jìn)行請(qǐng)求網(wǎng)絡(luò)數(shù)據(jù)的使用
這篇文章主要介紹了Android中Volley框架進(jìn)行請(qǐng)求網(wǎng)絡(luò)數(shù)據(jù)的使用,本文給大家介紹的非常詳細(xì)具有參考借鑒價(jià)值,需要的朋友可以參考下2016-10-10Android?Flutter控件封裝之視頻進(jìn)度條的實(shí)現(xiàn)
這篇文章主要來(lái)和大家分享一個(gè)很簡(jiǎn)單的控制器封裝案例,包含了基本的播放暫停,全屏和退出全屏,文中的示例代碼講解詳細(xì),感興趣的可以了解一下2023-06-06Kotlin 使用Lambda來(lái)設(shè)置回調(diào)的操作
這篇文章主要介紹了Kotlin 使用Lambda來(lái)設(shè)置回調(diào)的操作方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-03-03Android自定義View實(shí)現(xiàn)漸變色儀表盤
這篇文章主要為大家詳細(xì)介紹了Android自定義View實(shí)現(xiàn)漸變色儀表盤,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-11-11