Android React-Native通信数据模型分析

无论是计算机领域还是日常生活中,我们所言的通信,其核心都是数据信息的交换,而数据模型的优劣对通信效率有着决定性的作用。

在React-Native项目中,Javascript语言与Native两种语言(Java或OC等)间存在着大量的数据交换,也就是所谓的通信。众所周知,移动APP对性能的要求无比苛刻,如果通信数据模型设计地不合理,很可能引起多线程下的数据安全问题,以及应用性能问题,比如内存泄漏,UI绘制缓慢等。

前面几篇博客我们详细分析过React-Native的通信机制,主要有两个方向: Java->Bridge->Javascript和Javascript->Bridge->Java。所以,真正的数据交换其实发生在Java与Bridge,Javascript与Bridge两个环节。

Javascript与Bridge间的数据通信是借助于Webkit使用Json完成,简单实用,水到渠成,不多分析。而Java与Bridge间的数据通信相比之下就复杂多了,作为真正运行在设备上的程序语言,这恰恰是决定整个通信过程效率高低最核心的一环,也是本篇博客研究的内容。

Java是Android应用程序的本地开发语言,而Bridge是使用C++开发的动态链接库,由Java语言通过JNI的方式调用。Java与Bridge间的数据通信,实质是Java和C++两种程序语言间的数据传输,而传递的方向又分为两个场景:Java传输数据给C++ 和C++ 传输数据给Java。

我们先来看第一种场景。

Java主动向Javascript通信,主要是通过ReactBridge.java类的callFunction方法,将需要调用的组件(moduleId)、功能(methodId)、数据(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); ... }

我们可以看到,传输的数据类型是NativeArray,来瞧下具体的代码,位于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是一个抽象类,其中,只有一个HybridData类型成员变量,由其构造方法赋值初始化。

NativeArray还有一个名为ReadableNativeArray的直接子类,和一个名为WritableNativeArray的间接子类,后者是继承于前者。顾名思义,一个是用于读数据,一个是用于写数据。

Java向Bridge传输数据,自然就是写数据了,所以我们先来看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个写数据的native方法,涵盖了int、string,array,map等不同的数据类型和结构。

还有一个名为initHybrid()的native方法,用于创建HybridData类的实例,然后通过构造方法给其超父类NativeArray的mHybridData成员变量赋值,具体作用后面来分析,先略过。

接下来,我们来验证一下WritableNativeArray是否是真正传输给Bridge的数据类型。

Java调用Javascript组件,都是由名为JavaScriptModuleInvocationHandler的动态代理类统一拦截处理的吗?来回顾一下代码,位于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方法传递的参数类型是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; }

正如我们猜测的一般,fromJavaArgs静态方法返回的是一个新创建的WritableNativeArray对象实例,然后按照数据类型,调用相应的push方法。有些特殊的是,int型和float型都当成了double型来处理,这样做并不会造成数据的损害。

刚刚说到,WritableNativeArray的所有写入数据的方法都是native方法,即Java层面的通信数据全部是直接写入到Bridge层的,换言之,WritableNativeArray仅仅起到了数据传输管道的作用。这样做,有两个好处:

1、数据只在C++存有一份,这样避免了数据具有多个副本,节省了一部分的内存。

2、减小对WritableNativeArray对象的依赖,使其容易释放,可以由虚拟机GC自动回收内存。

那么,在Bridge层中,C++又是如何处理push过来的数据的呢?

先来看一下WritableNativeArray中native方法在JNI中动态注册的代码,位于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++中也存在着一个名为WritableNativeArray的类,具有与着native方法相对应的方法,巧的是,它也是继承于ReadableNativeArray类(注意HybridClass模板类的第二个泛型表示父类):

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; } ... }

看到这里,我们不禁会猜测,C++中的ReadableNativeArray类很可能也是继承于NativeArray。

当然,事实确实是这样的。在C++中存在着与Java中完全呼应的三个类:NativeArray、ReadableNativeArray、WritableNativeArray,命名和继承关系都是完全一致的!

而且可以看到,所有的数据都被存储到父类NativeArray的array变量中。

不过,问题来了!

C++中的WritableNativeArray对象和Java中的WritableNativeArray两个同名对象间是否存在着某种联系呢,比如一一映射的关系?

答案是肯定的! 因为每当一个Java层的WritableNativeArray对象被创建,在C++层都会有一个相应的WritableNativeArray对象被创建,用来接收Java层push过来的数据。

再来回顾下WritableNativeArray.java创建的过程。

public class WritableNativeArray extends ReadableNativeArray implements WritableArray { ... public WritableNativeArray() { super(initHybrid()); } ... private native static HybridData initHybrid(); ... }

在构造WritableNativeArray的时候,会通过initHybrid方法创建一个HybridData对象,并保存到其超父类NativeArray的成员变量mHybridData中。

而HybridData对象又是什么呢?

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"); } ... }

构造函数中Prerequisites.ensure(),是用来加载fbjni动态链接库的。

在HybridData 类中,有一个long的私有成员变量,根据注释和名字可以猜测与C++指针相关,具体是不是这样呢?我们来看HybridData对象通过initHybrid()初始化的过程。

代码位于react/jni/OnLoad.cpp中:

struct WritableNativeArray : public jni::HybridClass<WritableNativeArray, ReadableNativeArray> { ... static local_ref<jhybriddata> initHybrid(alias_ref<jclass>) { return makeCxxInstance(); } ... }

这里的jhybriddata指的就是HybridData(Java)对象,其是通过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在这里对在JNI中创建Java对象的过程做了非常高效的封装,即JavaClass对象。所有JavaClass的子类都通过一个名为kJavaDescriptor的字符串指针,来描述相对应的Java对象类名。

继续来看makeCxxInstance()是如何创建HybridData(Java) 对象的。代码同样在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)...))); } ... }

结合下前面的WritableNativeArray(C++)来看

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(); } ... }

在创建HybridData(Java)的时候,模板类HybridClass的第一个泛型T,表示的是WritableNativeArray(C++)这个结构体。所以,makeHybridData中的new T(std::forward(args)…)新创建的T就是WritableNativeArray(C++)对象。

继续来看makeHybridData方法,参数cxxPart是刚刚创建的WritableNativeArray对象的指针。里面通过detail::HybridData::create()真正创建了HybridData(Java)和HybridData(C++)对象,并将WritableNativeArray(C++)对象的指针通过setNativePointer方法注入到了HybridData(Java)中。

接下来,看create和setNativePointer两个方法的细节,在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里面是通过newInstance方式创建了HybridData(Java) 和HybridData(C++)对象,具体细节不细说了,读者自行去研究facebook的封装。

HybridData(C++)的setNativePointer方法中的参数new_value,为WritableNativeArray(C++)对象的指针, 使用reinterpret_cast关键字将其转换成long型,设置到mNativePointer中。而这里的mNativePointer,就是我们前面谈到的HybridData(Java)类的成员变量了!

有一点需要注意的是,保存WritableNativeArray(C++)对象指针的时候,会先获取原先保存的指针并删除回收(如果存在的话),主要目的是回收WritableNativeArray(C++)对象的内存,调用的时机是HybridData(Java)的finalize,也就是WritableNativeArray(Java)和HybridData(Java)被虚拟机GC回收的时候,这说明了一点,就是WritableNativeArray(C++)对象实例和WritableNativeArray(Java)对象实例的内存释放是完全同步的,都是交由Java GC来触发!

到这里我们稍稍梳理一下。

当WritableNativeArray(Java)创建的时候,通过JNI调用会先创建WritableNativeArray(C++)对象,其后会创建HybridData(Java)和HybridData(C++),同时将WritableNativeArray(C++)的指针保存到HybridData(Java)的mNativePointer成员变量中,最后把HybridData(Java)保存到WritableNativeArray(Java)对象里面。

这样设计有一个好处。当WritableNativeArray(Java)通过JNI的方式传递到C++层时,可以通过保存在其内部的HybridData(Java)对象的mNativePointer的值,还原WritableNativeArray(C++)对象。

这个还原过程是通过内联函数cthis函数实现的,代码在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)对象的mHybridData,再提取其mNativePointer,最后使用reinterpret_cast还原出WritableNativeArray(C++)对象。而在WritableNativeArray(C++)对象中存储着所有push的数据(定义在其父类NativeArray中),这样数据的提取工作就完成了。

到此,Java传输数据给C++的场景分析完成,下面我们来研究反向过程。

C++传输数据给Java的场景,主要是在callNativeModules里面,我们直接来看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是一个封装好的folly::dynamic对象(详见folly开源库),通过newObjectCxxArgs方法转换成ReadableNativeArray(C++)对象,实现在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...); }

创建ReadableNativeArray(C++)对象的过程和前面创建WritableNativeArray(C++)对象的过程一模一样。先创建HybridData(Java)和HybridData(C++),同时将ReadableNativeArray(C++)的指针保存到HybridData(Java)的mNativePointer成员变量中。最后ReadableNativeArray(Java)对象被封装在JavaPart中(再次用到facebook用JNI创建Java对象的封装库),通过get方法获取到真正的实例。

继续来看ReadableNativeArray(Java),位于包com.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)同样也是一个管道,所有数据仍然是存在C++层,必须全部通过native本地方法来提取,依赖具有了前面说到的两个优点:减少内存和容易回收。

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), }); }

对数据的提取,最后仍然是对array对象操作,其是定义在父类NativeArray.h中的,不在赘述。

整个数据模型的分析就到此结束了,总结一下有以下几个特点:

1、数据只有一份存储,即在C++中,无论是ReadableNativeArray(Java)还是WritableNativeArray(Java)都只是数据存取的管道。

2、ReadableNativeArray和WritableNativeArray在Java层和C++层又都有各自的实例,通过Java层实例的HybridData的mNativePointer作为纽带链接,其存储的是C++层实例的指针。

3、无论是Java层还是C++层的ReadableNativeArray和WritableNativeArray都是统一由Java GC进行回收管理。

感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!

时间: 2024-09-20 07:29:57

Android React-Native通信数据模型分析的相关文章

Android React-Native通信数据模型分析_Android

无论是计算机领域还是日常生活中,我们所言的通信,其核心都是数据信息的交换,而数据模型的优劣对通信效率有着决定性的作用. 在React-Native项目中,Javascript语言与Native两种语言(Java或OC等)间存在着大量的数据交换,也就是所谓的通信.众所周知,移动APP对性能的要求无比苛刻,如果通信数据模型设计地不合理,很可能引起多线程下的数据安全问题,以及应用性能问题,比如内存泄漏,UI绘制缓慢等. 前面几篇博客我们详细分析过React-Native的通信机制,主要有两个方向: J

Android React Native原生模块与JS模块通信的方法总结

Android React Native原生模块与JS模块通信的方法总结 前言: 在做React Native开发的时候避免不了的需要原生模块和JS之间进行数据传递,这篇文章将向大家分享原生模块向JS传递数据的几种方式. 方式一:通过Callbacks的方式 说起Callbacks大家都不陌生,它是最常用的设计模式之一.无论是Java,Object-c,C#,还是JavaScript等都会看到Callbacks的身影. 原生模块支持Callbacks类型的参数,该Callbacks对应JS中的f

react native android

问题描述 react native android react native android发布时候怎么修改默认链接的网址?

React Native移动开发资料库

本文整理了React Native开发中额优秀博客,以及优秀的Github库列表(很多英文资料源自于awesome-react-native) 关于开源库类 Star 100+ ️ Star 200+ ️️ Star 500+ ️️️ Star 1000+ ️️️️ Star 2000+ ️️️️️ 关于博客和视频类 值得读读 ️ 建议阅读 ️️ 强烈推荐 ️️️ 目录 网址 完整开源项目 Libraries (Star 100+) 中文博客 英文博客 视频资料 网址 源代码 官方文档 reac

React Native自动化测试

大凡做软件开发,肯定会涉及到很多的测试,本地测试,Junit测试,用例测试等,今天就来说说RN的测试. React Native的官方代码仓库里有一些测试代码,你可以在贡献代码之后回归测试一下,以检测有没有引起别的问题.这些测试是通过Travis持续集成系统来运行的,并且会自动针对你提交的代码给出测试结果. 当然我们的测试不可能有完整的覆盖率(尤其对于复杂的用户交互),所以很多更改也还需要仔细的人工审查.我们期待你能帮助我们提高测试覆盖率,以及提供更多的测试代码或是测试用例. 使用Jest来测试

React Native Android入门实战及深入源码分析系列(1)——Hello world

转载需注明出处:http://blog.csdn.net/minimicall?viewmode=contents 从今天起,我要分析React Native for Android的源码. 本系列主要是从使用和源码分析的角度来一步步的剖析React Native Android.当然,因为我对IOS不了解,所以,我只能分析安卓了. 首先来一个Hello world. 对于Rn 安卓的开发环境,本着不重复造轮子的思想,我就不再这里介绍了. 1. 创建一个工程 首先,我们需要创建一个Rn工程,通过

React Native Android入门实战及深入源码分析系列(2)——React Native源码编译

本文为老曾原创,转载需注明出处:http://blog.csdn.net/minimicall?viewmode=contents 在上一节中,我们通过一个相册的制作来学习了React Native编写.这一节我们需要开始学习React Native的源码. 学习源码,从编译源码开始. 首先,我们需要把代码从github中克隆下来. https://github.com/facebook/react-native.git 然后,我们可以切换到它的稳定分支,2016-03-30是我的操作时间,这个

React native for Android 初步实践

Facebook 于2015年9月15日推出react native for Android 版本, 加上2014年底已经开源的IOS版本,至此RN (react-native)真正成为跨平台的客户端框架.本篇主要是从分析代码入手,探讨一下RN在安卓平台上是如何构建一套JS的运行框架. 一. 整体架构 RN 这套框架让 JS开发者可以大部分使用JS代码就可以构建一个跨平台APP. Facebook官方说法是learn once, run everywhere, 即在Android . IOS.

React Native架构分析

Facebook 于2015年9月15日推出react native for Android 版本, 加上2014年底已经开源的IOS版本,至此RN (react-native)真正成为跨平台的客户端框架.本篇主要是从分析代码入手,探讨一下RN在安卓平台上是如何构建一套JS的运行框架. 一. 整体架构 RN 这套框架让 JS开发者可以大部分使用JS代码就可以构建一个跨平台APP. Facebook官方说法是learn once, run everywhere, 即在Android . IOS.