概述
这篇文章首先会展示react native的一个简单的访问网络请求的例子。然后会分析代码的实现。
注:
1.本文示例及代码分析基于react native 0.40版本。
2.限于水平有限,c++代码部分分析比较简单。期望更正,谢谢。
基本示例
注:示例来自http://www.jb51.cc/article/p-fydpvysd-bqm.html,并做了一些修改。
效果
代码
render() {
return (
<View style={styles.container}>
<ActivityIndicator animating={this.state.isLoading} />
<Text style={styles.welcome} onPress={this.requestNowWeatherFromServer.bind(this)}>
点我测试网络
</Text>
<Text style={styles.instructions}>
{this.state.resultJson}
</Text>
</View>
);
}
可以看到用户点击“点我测试网络”,会调用this.requestNowWeatherFromServer.bind(this)方法
requestNowWeatherFromServer(){
if(this.state.isLoading==true){
return;
}
this.setState({
resultJson:null,isLoading:true
});
try {
NetworkService.requestNowWeatherFromServer()
.then((response) => { let data = response; this.setState({ resultJson:data==null?null:JSON.stringify(data),isLoading:false }); console.log("返回数据:"+JSON.stringify(data)); }) } catch(e) { alert(e); this.setState({ isLoading:false }); } }
首先,如果isLoading为true,直接返回(防止重复点击)。然后,调用NetworkService.requestNowWeatherFromServer请求网络。最后将网络请求的返回值赋值给resultJson。
import NetworkService from './network.api.js';
NetworkService是network.api.js这个文件中定义的,具体如下:
//和风天气
const baseURL = "https://free-api.heweather.com/v5/";
function requestFromServer(...props) {
this.url = props.shift(1);
this.options = props.shift(1);
return fetch(this.url,Object.assign({},this.options))
.then((response) => {
return response.json()
});
}
export default {
//http://docs.heweather.com/224326
requestNowWeatherFromServer() {
var subURL = "now?city=beijing&key=9e6aa5cbcb994295ae8e54da94f48bba";
return requestFromServer(`${baseURL}/${subURL}`,{
method: 'get',headers: {
'Accept': 'application/json','Content-Type': 'application/json',},});
}
};
可以看到requestNowWeatherFromServer方法调用了requestFromServer方法,最终调用了react native提供的fetch方法。
fetch方法返回了response.json()给调用端,最终赋值给了state.resultJson:
<Text style={styles.instructions}>
{this.state.resultJson}
</Text>
state.resultJson是Text使用的,这样就将网络请求的结果展示出来。
注意事项
-1.fetch方法支持get、post,支持header。post示例如下
fetch(url,{ method: 'POST',headers: { 'Accept': 'application/json',},body: JSON.stringify({ firstParam: 'firstValue',secondParam: 'secondValue',})
})
-2.底层实现默认不支持https,需要修改代码
修改MainApplication
@Override
public void onCreate() {
super.onCreate();
OkHttpClientProvider.replaceOkHttpClient(HttpsOkHttpClient.initCustomOkHttpClient());//为了支持https,替换默认的okhttpClient
SoLoader.init(this,/* native exopackage */ false);
}
调用OkHttpClientProvider.replaceOkHttpClient替换为自己的OkHttpClient。
OkHttpClient通过HttpsOkHttpClient.initCustomOkHttpClient()构建并返回
public class HttpsOkHttpClient {
/** * react native默认不支持https请求,这里提供支持https的OKHttpClient * @return */
public static OkHttpClient initCustomOkHttpClient(){
OkHttpClient.Builder client = new OkHttpClient.Builder()
.connectTimeout(0,TimeUnit.MILLISECONDS)
.readTimeout(0,TimeUnit.MILLISECONDS)
.writeTimeout(0,TimeUnit.MILLISECONDS)
.cookieJar(new ReactCookieJarContainer());
OkHttpClient.Builder builder = OkHttpClientProvider.enableTls12OnPreLollipop(client);
builder.sslSocketFactory(getSSLSocketFactory())
.hostnameVerifier(new HostnameVerifier() {
@Override
public boolean verify(String hostname,SSLSession session) {
return true; //忽略所有的认证,直接返回了true
}
});
return builder.build();
}
private static SSLSocketFactory getSSLSocketFactory() {
TrustManager[] trustAllCerts = new TrustManager[]{new X509TrustManager() {
public void checkClientTrusted(X509Certificate[] chain,String authType) throws
CertificateException {
}
public void checkServerTrusted(X509Certificate[] chain,String authType) throws CertificateException {
}
public X509Certificate[] getAcceptedIssuers() {
return new X509Certificate[0];
}
}};
SSLSocketFactory sslSocketFactory = null;
try {
SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init((KeyManager[])null,trustAllCerts,new SecureRandom());
sslSocketFactory = sslContext.getSocketFactory();
} catch (Exception e) {
e.printStackTrace();
}
return sslSocketFactory;
}
}
实现原理
原理概述
图片来自http://www.jb51.cc/article/p-ahzjgpxg-up.html
如上图,react native在android设备上最终使用的的原生的UI控件:包括UI、网络请求等。而react native完全是用js来开发。js代码就是通过C++代码同java端进行双向映射的。类似与普通android开发中的webview控件与js交互的过程,react native使用了自己的webkit内核。
初始化
初始化java层
react-native自动生成的android代码有MainApplication和MainActivity
public class MainApplication extends Application implements ReactApplication {
//属性
private final ReactNativeHost mReactNativeHost = new ReactNativeHost(this) {
@Override
protected boolean getUseDeveloperSupport() {
return BuildConfig.DEBUG;
}
@Override
protected List<ReactPackage> getPackages() {
//返回了ReactPackage的子类MainReactPackage
return Arrays.<ReactPackage>asList(
new MainReactPackage()
);
}
};
@Override
public ReactNativeHost getReactNativeHost() {
return mReactNativeHost;
}
@Override
public void onCreate() {
super.onCreate();
SoLoader.init(this,/* native exopackage */ false);
}
}
public interface ReactApplication {
/** * Get the default {@link ReactNativeHost} for this app. * 获取react-native的配置类 */
ReactNativeHost getReactNativeHost();
}
ReactPackage是设置配置信息的接口,如下:
public interface ReactPackage {
//返回原生模块的配置集合,用于js代码调用原生代码
List<NativeModule> createNativeModules(ReactApplicationContext reactContext);
//返回js模块的配置集合,用于原生代码调用js代码
List<Class<? extends JavaScriptModule>> createJSModules();
List<ViewManager> createViewManagers(ReactApplicationContext reactContext);
}
ReactPackage有两个子类MainReactPackage、CoreModulesPackage后面初始化的时候会用到。其中MainReactPackage里面有网络请求模块的相关配置,如下:
public List<ModuleSpec> getNativeModules(final ReactApplicationContext reactContext) {
List<ModuleSpec> moduleSpecList = new ArrayList<>();
moduleSpecList.add(new ModuleSpec(NetworkingModule.class,new Provider<NativeModule>() {
@Override
public NativeModule get() {
//网络请求的module
return new NetworkingModule(context);
}
});
//这里省略了其他模块
return moduleSpecList;
MainActivity
public class MainActivity extends ReactActivity {
/** * Returns the name of the main component registered from JavaScript. * This is used to schedule rendering of the component. */
@Override
protected String getMainComponentName() {
return "AwesomeProject";
}
}
MainActivity继承了ReactActivity
public abstract class ReactActivity extends Activity implements DefaultHardwareBackBtnHandler,PermissionAwareActivity {
private final ReactActivityDelegate mDelegate;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//调用了ReactActivityDelegate的onCreate方法
mDelegate.onCreate(savedInstanceState);
}
@Override
protected void onPause() {
super.onPause();
mDelegate.onPause();
}
@Override
protected void onResume() {
super.onResume();
mDelegate.onResume();
}
@Override
protected void onDestroy() {
super.onDestroy();
mDelegate.onDestroy();
}
ReactActivityDelegate
protected void onCreate(Bundle savedInstanceState) {
//忽略部分代码
loadApp(mMainComponentName);
}
protected void loadApp(String appKey) {
if (mReactRootView != null) {
throw new IllegalStateException("Cannot loadApp while app is already running.");
}
mReactRootView = createRootView();
//调用了ReactRootView的startReactApplication方法
mReactRootView.startReactApplication(
getReactNativeHost().getReactInstanceManager(),appKey,getLaunchOptions());
//设置contentView
getPlainActivity().setContentView(mReactRootView);
}
ReactRootView.java
public void startReactApplication(
ReactInstanceManager reactInstanceManager,String moduleName,@Nullable Bundle launchOptions) {
//省略部分代码
mReactInstanceManager = reactInstanceManager;
mJSModuleName = moduleName;
mLaunchOptions = launchOptions;
if (!mReactInstanceManager.hasStartedCreatingInitialContext()) {
mReactInstanceManager.createReactContextInBackground();
}
}
XReactInstanceManagerImpl.java
public void recreateReactContextInBackground() {
recreateReactContextInBackgroundInner();
}
private void recreateReactContextInBackgroundInner() {
recreateReactContextInBackgroundFromBundleLoader();
}
private void recreateReactContextInBackgroundFromBundleLoader() {
recreateReactContextInBackground(
new JSCJavaScriptExecutor.Factory(mJSCConfig.getConfigMap()),mBundleLoader);
}
private void recreateReactContextInBackground(
JavaScriptExecutor.Factory jsExecutorFactory,JSBundleLoader jsBundleLoader) {
ReactContextInitParams initParams =
new ReactContextInitParams(jsExecutorFactory,jsBundleLoader);
// No background task to create react context is currently running,create and execute one.
//创建了ReactContextInitAsyncTask对象并调用
mReactContextInitAsyncTask = new ReactContextInitAsyncTask();
mReactContextInitAsyncTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR,initParams);
}
ReactContextInitAsyncTask.java
private final class ReactContextInitAsyncTask extends AsyncTask<ReactContextInitParams,Void,Result<ReactApplicationContext>> {
@Override
protected Result<ReactApplicationContext> doInBackground(ReactContextInitParams... params) {
Process.setThreadPriority(Process.THREAD_PRIORITY_DEFAULT);
try {
JavaScriptExecutor jsExecutor = params[0].getJsExecutorFactory().create();
return Result.of(createReactContext(jsExecutor,params[0].getJsBundleLoader()));
} catch (Exception e) {
// Pass exception to onPostExecute() so it can be handled on the main thread
return Result.of(e);
}
}
}
调用了XReactInstanceManagerImpl的createReactContext方法
private ReactApplicationContext createReactContext(
JavaScriptExecutor jsExecutor,JSBundleLoader jsBundleLoader) {
mSourceUrl = jsBundleLoader.getSourceUrl();
//原生模块集合初始化
List<ModuleSpec> moduleSpecs = new ArrayList<>();
Map<Class,ReactModuleInfo> reactModuleInfoMap = new HashMap<>();
JavaScriptModuleRegistry.Builder jsModulesBuilder = new JavaScriptModuleRegistry.Builder();
final ReactApplicationContext reactContext = new ReactApplicationContext(mApplicationContext);
try {
//ReactPackage的子类,配置文件1
CoreModulesPackage coreModulesPackage =
new CoreModulesPackage(this,mBackBtnHandler,mUIImplementationProvider);
//这里将coreModulesPackage里面的配置信息解析到moduleSpecs集合中
processPackage(
coreModulesPackage,reactContext,moduleSpecs,reactModuleInfoMap,jsModulesBuilder);
} finally {
Systrace.endSection(TRACE_TAG_REACT_JAVA_BRIDGE);
}
//mPackages集合中存在MainReactPackage的对象,是在XReactInstanceManagerImpl构造函数中赋值的
for (ReactPackage reactPackage : mPackages) {
try {
//这里将reactPackage里面的配置信息解析到moduleSpecs集合中
processPackage(
reactPackage,jsModulesBuilder);
} finally {
Systrace.endSection(TRACE_TAG_REACT_JAVA_BRIDGE);
}
}
//省略部分代码
//剩下代码下面内容会分析
}
先看processPackage方法
private void processPackage( ReactPackage reactPackage,ReactApplicationContext reactContext,List<ModuleSpec> moduleSpecs,Map<Class,ReactModuleInfo> reactModuleInfoMap,JavaScriptModuleRegistry.Builder jsModulesBuilder) { //获取原生模块配置、解析添加到moduleSpecs中 for (NativeModule nativeModule : reactPackage.createNativeModules(reactContext)) { moduleSpecs.add( new ModuleSpec(nativeModule.getClass(),new EagerModuleProvider(nativeModule))); } for (Class<? extends JavaScriptModule> jsModuleClass : reactPackage.createJSModules()) { jsModulesBuilder.add(jsModuleClass); } } //LazyReactPackage.java中的方法 @Override public final List<NativeModule> createNativeModules(ReactApplicationContext reactContext) { List<NativeModule> modules = new ArrayList<>(); for (ModuleSpec holder : getNativeModules(reactContext)) { modules.add(holder.getProvider().get()); } return modules; } //MainReactPackage.java中的方法,里面有网络请求等原生模块的初始化配置信息 public List<ModuleSpec> getNativeModules(final ReactApplicationContext reactContext) { List<ModuleSpec> moduleSpecList = new ArrayList<>(); moduleSpecList.add(new ModuleSpec(NetworkingModule.class,new Provider<NativeModule>() { @Override public NativeModule get() { //网络请求的module return new NetworkingModule(context); } }); //这里省略了其他模块 return moduleSpecList;
经过processPackage方法,moduleSpecs里面就存放了所有原生模块的配置信息。
createReactContext方法调用完processPackage后的代码片段如下:
private ReactApplicationContext createReactContext(
JavaScriptExecutor jsExecutor,JSBundleLoader jsBundleLoader) {
//moduleSpecs构造NativeModuleRegistry对象
NativeModuleRegistry nativeModuleRegistry = new NativeModuleRegistry(moduleSpecs,reactModuleInfoMap);
CatalystInstanceImpl.Builder catalystInstanceBuilder = new CatalystInstanceImpl.Builder()
.setReactQueueConfigurationSpec(ReactQueueConfigurationSpec.createDefault())
.setJSExecutor(jsExecutor)
.setRegistry(nativeModuleRegistry)
.setJSModuleRegistry(jsModulesBuilder.build())
.setJSBundleLoader(jsBundleLoader);
final CatalystInstance catalystInstance = catalystInstanceBuilder.build();
reactContext.initializeWithInstance(catalystInstance);
catalystInstance.runJSBundle();
return reactContext;
}
moduleSpecs配置信息构造了NativeModuleRegistry对象:
//成员遍历,保存所有原生模块 private final Map<Class<? extends NativeModule>,ModuleHolder> mModules; public NativeModuleRegistry( List<ModuleSpec> moduleSpecList,Map<Class,ReactModuleInfo> reactModuleInfoMap) { Map<String,Pair<Class<? extends NativeModule>,ModuleHolder>> namesToSpecs = new HashMap<>(); //遍历原生模块配置集合moduleSpecList的每一个模块配置 for (ModuleSpec module : moduleSpecList) { Class<? extends NativeModule> type = module.getType(); ModuleHolder holder = new ModuleHolder( type,reactModuleInfoMap.get(type),module.getProvider()); String name = holder.getInfo().name(); Class<? extends NativeModule> existing = namesToSpecs.containsKey(name) ? namesToSpecs.get(name).first : null; namesToSpecs.put(name,new Pair<Class<? extends NativeModule>,ModuleHolder>(type,holder)); } mModules = new HashMap<>(); for (Pair<Class<? extends NativeModule>,ModuleHolder> pair : namesToSpecs.values()) { //添加配置信息到原生模块集合中 mModules.put(pair.first,pair.second); } }
接下来将创建的nativeModuleRegistry对象传递给CatalystInstanceImpl.Builder对象并调用build()方法构造CatalystInstanceImpl对象
CatalystInstanceImpl.Builder catalystInstanceBuilder = new CatalystInstanceImpl.Builder()
.setReactQueueConfigurationSpec(ReactQueueConfigurationSpec.createDefault())
.setJSExecutor(jsExecutor)
.setRegistry(nativeModuleRegistry)
.setJSModuleRegistry(jsModulesBuilder.build())
.setJSBundleLoader(jsBundleLoader)
.setNativeModuleCallExceptionHandler(exceptionHandler);
final CatalystInstance catalystInstancecatalystInstance = catalystInstanceBuilder.build();
CatalystInstanceImpl的构造方法如下:
private CatalystInstanceImpl(
final ReactQueueConfigurationSpec ReactQueueConfigurationSpec,final JavaScriptExecutor jsExecutor,final NativeModuleRegistry registry,final JavaScriptModuleRegistry jsModuleRegistry,final JSBundleLoader jsBundleLoader,NativeModuleCallExceptionHandler nativeModuleCallExceptionHandler) {
mHybridData = initHybrid();
mReactQueueConfiguration = ReactQueueConfigurationImpl.create(
ReactQueueConfigurationSpec,new NativeExceptionHandler());
mBridgeIdleListeners = new CopyOnWriteArrayList<>();
//原生模块赋值给了成员变量mJavaRegistry
mJavaRegistry = registry;
mJSModuleRegistry = jsModuleRegistry;
mJSBundleLoader = jsBundleLoader;
mNativeModuleCallExceptionHandler = nativeModuleCallExceptionHandler;
mTraceListener = new JSProfilerTraceListener(this);
initializeBridge(
new BridgeCallback(this),jsExecutor,mReactQueueConfiguration.getJSQueueThread(),mReactQueueConfiguration.getNativeModulesQueueThread(),//调用了NativeModuleRegistry的getModuleRegistryHolder方法
mJavaRegistry.getModuleRegistryHolder(this));
mMainExecutorToken = getMainExecutorToken();
}
NativeModuleRegistry.java
ModuleRegistryHolder getModuleRegistryHolder(
CatalystInstanceImpl catalystInstanceImpl) {
ArrayList<JavaModuleWrapper> javaModules = new ArrayList<>();
ArrayList<CxxModuleWrapper> cxxModules = new ArrayList<>();
//遍历所有module,添加到javaModules集合中
for (Map.Entry<Class<? extends NativeModule>,ModuleHolder> entry : mModules.entrySet()) {
Class<?> type = entry.getKey();
ModuleHolder moduleHolder = entry.getValue();
if (BaseJavaModule.class.isAssignableFrom(type)) {
javaModules.add(new JavaModuleWrapper(catalystInstanceImpl,moduleHolder));
} else if (CxxModuleWrapper.class.isAssignableFrom(type)) {
cxxModules.add((CxxModuleWrapper) moduleHolder.getModule());
} else {
throw new IllegalArgumentException("Unknown module type " + type);
}
}
//返回 ModuleRegistryHolder对象
return new ModuleRegistryHolder(catalystInstanceImpl,javaModules,cxxModules);
}
ModuleRegistryHolder.java
public class ModuleRegistryHolder {
private final HybridData mHybridData;
//将javaModules原生模块配置信息通过JNI传递到了C++层
private static native HybridData initHybrid(
CatalystInstanceImpl catalystInstanceImpl,Collection<JavaModuleWrapper> javaModules,Collection<CxxModuleWrapper> cxxModules);
public ModuleRegistryHolder(CatalystInstanceImpl catalystInstanceImpl,Collection<CxxModuleWrapper> cxxModules) {
//调用native方法
mHybridData = initHybrid(catalystInstanceImpl,cxxModules);
}
}
返回的ModuleRegistryHolder对象,传递给了CatalystInstanceImpl的native方法initializeBridge,如下:
private native void initializeBridge(ReactCallback callback,JavaScriptExecutor jsExecutor,MessageQueueThread jsQueue,MessageQueueThread moduleQueue,ModuleRegistryHolder registryHolder);
初始化c层
c++代码看不太懂,调用流程走不通。请指教。
下面只列出了关键代码:
ProxyExecutor::ProxyExecutor(jni::global_ref<jobject>&& executorInstance,std::shared_ptr<ExecutorDelegate> delegate)
: m_executor(std::move(executorInstance)),m_delegate(delegate) {
folly::dynamic nativeModuleConfig = folly::dynamic::array;
{
SystraceSection s("collectNativeModuleDescriptions");
//获取原生模块配置集合
auto moduleRegistry = delegate->getModuleRegistry();
//遍历集合,将配置信息添加到nativeModuleConfig中
for (const auto& name : moduleRegistry->moduleNames()) {
auto config = moduleRegistry->getConfig(name);
nativeModuleConfig.push_back(config ? config->config : nullptr);
}
}
//remoteModuleConfig是__fbBatchedBridgeConfig变量的一个属性,值为nativeModuleConfig
folly::dynamic config =
folly::dynamic::object
("remoteModuleConfig",std::move(nativeModuleConfig));
SystraceSection t("setGlobalVariable");
//设置了js全局变量__fbBatchedBridgeConfig为config的json格式字符串
setGlobalVariable(
"__fbBatchedBridgeConfig",folly::make_unique<JSBigStdString>(folly::toJson(config)));
}
初始化小结
应用启动的时候(ReactActivity onCreate方法被调用)初始化了所有java模块,并将java模块信息设置成js全局变量__fbBatchedBridgeConfig以供调用。以网络模块举例如下:
NetworkingModule.java里面是网络请求模块提供的三个网络请求方法:
@ReactModule(name = "RCTNetworking",supportsWebWorkers = true)
public final class NetworkingModule extends ReactContextBaseJavaModule {
//发送请求
@ReactMethod
public void sendRequest(
final ExecutorToken executorToken,String method,String url,final int requestId,ReadableArray headers,ReadableMap data,final String responseType,final boolean useIncrementalUpdates,int timeout) {//省略代码}
}
//取消请求
@ReactMethod
public void abortRequest(ExecutorToken executorToken,final int requestId) {
//省略代码
}
//清除cookie
@ReactMethod
public void clearCookies(
ExecutorToken executorToken,com.facebook.react.bridge.Callback callback) {
//省略代码
}
对应js端:
这样android端所有可以被js端调用的模块信息都暴露给了js,完成了初始化过程。
网络请求
网络请求js层
function requestFromServer(...props) {
this.url = props.shift(1);
this.options = props.shift(1);
//调用了fetch函数
return fetch(this.url,this.options))
.then((response) => {
return response.json()
});
}
- 2.fetch.js
fetch函数定义在fetch.js中
self.fetch = function(input,init) {
//参数input是请求的url
//init是请求参数,包括请求方式get、header等
return new Promise(function(resolve,reject) {
var request = new Request(input,init)
var xhr = new XMLHttpRequest()
//省略部分代码
xhr.send(typeof request._bodyInit === 'undefined' ? null : request._bodyInit)
})
}
该函数返回了一个Promise对象,该对象定义在core.js中
function Promise(fn) {
//忽略部分代码
doResolve(fn,this);
}
function doResolve(fn,promise) {
var done = false;
var res = tryCallTwo(fn,function (value) {//参数a
if (done) return;
done = true;
resolve(promise,value);
},function (reason) {//参数b
if (done) return;
done = true;
reject(promise,reason);
})
//忽略部分代码
}
function tryCallTwo(fn,a,b) {
try {
fn(a,b);
} catch (ex) {
LAST_ERROR = ex;
return IS_ERROR;
}
}
var xhr = new XMLHttpRequest()
//省略部分代码
xhr.send(typeof request._bodyInit === 'undefined' ? null : request._bodyInit)
xhr.send定义在XMLHttpRequest.js中
send(data: any): void {
//省略部分代码
RCTNetworking.sendRequest(
this._method,this._trackingName,this._url,this._headers,data,nativeResponseType,incrementalEvents,this.timeout,this.__didCreateRequest.bind(this),);
}
sendRequest(
method: string,trackingName: string,url: string,headers: Object,data: string | FormData | {uri: string},responseType: 'text' | 'base64',incrementalUpdates: boolean,timeout: number,callback: (requestId: number) => any
) { const body = typeof data === 'string' ? {string: data} :
data instanceof FormData ? {formData: getParts(data)} :
data;
const requestId = generateRequestId();
RCTNetworkingNative.sendRequest(
method,url,requestId,convertHeadersMapToArray(headers),{...body,trackingName},responseType,incrementalUpdates,timeout );
callback(requestId);
}
调用了RCTNetworkNative的sendRequest方法。
//RCTNetworkingNative的定义
const RCTNetworkingNative = require('NativeModules').Networking;
- 4.原生代码模块js端初始化
require(‘NativeModules’)的定义及赋值在NativeModules.js中:
let NativeModules : {[moduleName: string]: Object} = {};//定义
//上面初始化部分提到过:__fbBatchedBridgeConfig这个全局变量,是在初始化时通过JNI代码设置的。
//里面是所有暴露给js方法调用的模块。
const bridgeConfig = global.__fbBatchedBridgeConfig;
//遍历所有模块
(bridgeConfig.remoteModuleConfig || []).forEach((config: ModuleConfig,moduleID: number) => { // Initially this config will only contain the module name when running in JSC. The actual // configuration of the module will be lazily loaded. const info = genModule(config,moduleID);//生成每一个模块的所有方法 if (!info) { return; } //省略部分代码 if (info.module) { //上面的对象NativeModules.Networking就是这么生成的 NativeModules[info.name] = info.module; } });
//生成模块
function genModule(config: ?ModuleConfig,moduleID: number): ?{name: string,module?: Object} {
if (!config) {
return null;
}
const [moduleName,constants,methods,promiseMethods,syncMethods] = config;
const module = {};
//遍历该模块所有方法配置
methods && methods.forEach((methodName,methodID) => {
const isPromise = promiseMethods && arrayContains(promiseMethods,methodID);
const isSync = syncMethods && arrayContains(syncMethods,methodID);
const methodType = isPromise ? 'promise' : isSync ? 'sync' : 'async';
//调用genMethod生成方法
module[methodName] = genMethod(moduleID,methodID,methodType);
});
Object.assign(module,constants);
return { name: moduleName,module };
}
//动态生成模块里面的方法
function genMethod(moduleID: number,methodID: number,type: MethodType) {
let fn = null;
if (type === 'promise') {//promise类型
fn = function(...args: Array<any>) {
return new Promise((resolve,reject) => {
BatchedBridge.enqueueNativeCall(moduleID,args,(data) => resolve(data),(errorData) => reject(createErrorFromErrorData(errorData)));
});
};
} else if (type === 'sync') {//sync类型
fn = function(...args: Array<any>) {
return global.nativeCallSyncHook(moduleID,args);
};
} else {//普通类型
//fn就是根据配置动态生成的方法
//RCTNetworkingNative.sendRequest这个方法就是动态生成的
fn = function(...args: Array<any>) {
const lastArg = args.length > 0 ? args[args.length - 1] : null;
const secondLastArg = args.length > 1 ? args[args.length - 2] : null;
const hasSuccessCallback = typeof lastArg === 'function';
const hasErrorCallback = typeof secondLastArg === 'function';
hasErrorCallback && invariant(
hasSuccessCallback,'Cannot have a non-function arg after a function arg.'
);
const onSuccess = hasSuccessCallback ? lastArg : null;
const onFail = hasErrorCallback ? secondLastArg : null;
const callbackCount = hasSuccessCallback + hasErrorCallback;
args = args.slice(0,args.length - callbackCount);
BatchedBridge.enqueueNativeCall(moduleID,onFail,onSuccess);
};
}
fn.type = type;
return fn;
}
BatchedBridge.enqueueNativeCall定义在MessageQueue.js中
enqueueNativeCall(moduleID: number,params: Array<any>,onFail: ?Function,onSucc: ?Function) {
if (onFail || onSucc) {
onFail && params.push(this._callbackID);
this._callbacks[this._callbackID++] = onFail;
onSucc && params.push(this._callbackID);
this._callbacks[this._callbackID++] = onSucc;
}
this._callID++;
this._queue[MODULE_IDS].push(moduleID);//模块Id放入数组
this._queue[METHOD_IDS].push(methodID)//方法Id放入数组
this._queue[PARAMS].push(params);//参数放入数组
}
这里把要调用的模块id、方法id、参数放入_queue数组中。
//JNI代码调用情况1
callFunctionReturnFlushedQueue(module: string,method: string,args: Array<any>) {
this.__callFunction(module,method,args);
this.__callImmediates();
return this.flushedQueue();
}
//JNI代码调用情况2
callFunctionReturnResultAndFlushedQueue(module: string,args: Array<any>) {
let result;
result = this.__callFunction(module,args);
this.__callImmediates();
return [result,this.flushedQueue()];
}
//JNI代码调用情况3
invokeCallbackAndReturnFlushedQueue(cbID: number,args: Array<any>) {
this.__invokeCallback(cbID,args);
this.__callImmediates();
return this.flushedQueue();
}
flushedQueue() {
this.__callImmediates();
const queue = this._queue;
this._queue = [[],[],this._callID];
return queue[0].length ? queue : null;//这里返回了queue里面的内容
}
网络请求c层
JNI代码会调用flushedQueue方法,从而调用相应的原生模块中对应的方法,完成js到native端通信
c++代码不熟,水平不够(JNI端实现原理请参考系列文章:http://blog.csdn.net/MegatronKings/article/category/6377857)
网络请求java层
- 打断点原生代码入口是NativeRunnable,如下:
/** * A Runnable that has a native run implementation. */
@DoNotStrip
public class NativeRunnable implements Runnable {
private final HybridData mHybridData;
@DoNotStrip
private NativeRunnable(HybridData hybridData) {
mHybridData = hybridData;
}
public native void run();
}
@DoNotStrip
public void invoke(ExecutorToken token,int methodId,ReadableNativeArray parameters) {
if (mMethods == null || methodId >= mMethods.size()) {
return;
}
mMethods.get(methodId).invoke(mCatalystInstance,token,parameters);
}
其中参数parameters是一个数组,里面有各种网络参数,如下:
[“GET”,”https://free-api.heweather.com/v5//now?city=beijing&key=9e6aa5cbcb994295ae8e54da94f48bba“,4,[[“accept”,”application/json”],[“content-type”,”application/json”]],{“trackingName”:”unknown”},”text”,false,0]
@Override
public void invoke(CatalystInstance catalystInstance,ExecutorToken executorToken,ReadableNativeArray parameters) {
//省略部分代码
mMethod.invoke(BaseJavaModule.this,mArguments);
//省略部分代码
}
mMethod是NetworkingModule类的sendRequest方法:
- NetworkingModule.sendRequest方法
//实现这个注解的方法代表暴露给JNI的方法
@ReactMethod
/** * @param timeout value of 0 results in no timeout */
public void sendRequest(
final ExecutorToken executorToken,//GET、POST等
String url,//请求URL
final int requestId,//请求tag
ReadableArray headers,//请求header
ReadableMap data,//请求数据
final String responseType,//期望返回数据格式
final boolean useIncrementalUpdates,int timeout) {
Request.Builder requestBuilder = new Request.Builder().url(url);//网络请求使用OkHttp
if (requestId != 0) {
requestBuilder.tag(requestId);
}
//内部通过动态代理创建RCTDeviceEventEmitter的实例:用于将网络请求返回的数据返回给JNI端
final RCTDeviceEventEmitter eventEmitter = getEventEmitter(executorToken);
OkHttpClient.Builder clientBuilder = mClient.newBuilder();
if (timeout != mClient.connectTimeoutMillis()) {
clientBuilder.readTimeout(timeout,TimeUnit.MILLISECONDS);
}
OkHttpClient client = clientBuilder.build();
Headers requestHeaders = extractHeaders(headers,data);
if (requestHeaders == null) {
ResponseUtil.onRequestError(eventEmitter,requestId,"Unrecognized headers format",null);
return;
}
String contentType = requestHeaders.get(CONTENT_TYPE_HEADER_NAME);
String contentEncoding = requestHeaders.get(CONTENT_ENCODING_HEADER_NAME);
requestBuilder.headers(requestHeaders);
//忽略部分代码
// Nothing in data payload,at least nothing we could understand anyway.
requestBuilder.method(method,RequestBodyUtil.getEmptyBody(method));
client.newCall(requestBuilder.build()).enqueue(//开始请求网络
new Callback() {
@Override
public void onFailure(Call call,IOException e) {
//请求失败的回调
//忽略部分代码
ResponseUtil.onRequestError(eventEmitter,e.getMessage(),e);
}
@Override
public void onResponse(Call call,Response response) throws IOException {
//请求成功回调
//忽略部分代码
// Before we touch the body send headers to JS 返回headers给JNI
ResponseUtil.onResponseReceived(
eventEmitter,response.code(),translateHeaders(response.headers()),response.request().url().toString());
ResponseBody responseBody = response.body();
//忽略部分代码
// Otherwise send the data in one big chunk,in the format that JS requested.
String responseString = "";
if (responseType.equals("text")) {//如果请求参数中传递的是text,直接返回字符串
responseString = responseBody.string();
} else if (responseType.equals("base64")) {//请求参数中传递的是base64
responseString = Base64.encodeToString(responseBody.bytes(),Base64.NO_WRAP);
}
//返回response body给JNI
ResponseUtil.onDataReceived(eventEmitter,responseString);
ResponseUtil.onRequestSuccess(eventEmitter,requestId);
//忽略部分代码
}
});
}
可以看到,访问网络使用的是okhttp。根据请求参数构造request,并且加入到okhttp的队列中。这样就开始请求网络了。请求成功或者失败会调用ResponseUtil相应的方法。在成功的回调方法中,先把response的heades返回给JNI端(调用ResponseUtil.onResponseReceived),然后返回response体给JNI端(调用ResponseUtil.onDataReceived方法),最后调用ResponseUtil.onRequestSuccess通知JNI改网络请求完成。
下面只分析.ResponseUtil的onDataReceived方法(其他方法类似)。
网络返回java层
- ResponseUtil的onDataReceived方法
public static void onDataReceived(
RCTDeviceEventEmitter eventEmitter,//动态代理生成的对象
int requestId,//请求tag
String data) {//response body体中的内容
WritableArray args = Arguments.createArray();
args.pushInt(requestId);
args.pushString(data);
eventEmitter.emit("didReceiveNetworkData",args);//调用eventEmitter对象的emit方法
}
JavaScriptModule interfaceProxy = (JavaScriptModule) Proxy.newProxyInstance(
moduleInterface.getClassLoader(),new Class[]{moduleInterface},new JavaScriptModuleInvocationHandler(executorToken,instance,registration));
可以看到具体实现是在JavaScriptModuleInvocationHandler中:
- JavaScriptModuleInvocationHandler.invoke方法:
public @Nullable Object invoke(Object proxy,Method method,@Nullable Object[] args) throws Throwable { //省略部分代码 mCatalystInstance.callFunction( executorToken,mModuleRegistration.getName(),method.getName(),jsArgs ); return null; }
- CatalystInstanceImpl.callFunction方法
public void callFunction(
ExecutorToken executorToken,final String module,//值为:RCTDeviceEventEmitter
final String method,//值为:emit final NativeArray arguments) {//值为:["didReceiveNetworkData",[5,"response body"]] //忽略部分代码 callJSFunction(executorToken,module,arguments); }
callJSFunction是c++方法,如下:
private native void callJSFunction(
ExecutorToken token,String module,String method,NativeArray arguments);
网络返回c层
CatalystInstanceImpl.cpp
void CatalystInstanceImpl::callJSFunction(
JExecutorToken* token,std::string module,std::string method,NativeArray* arguments) {
//调用instance的callJSFunction方法
instance_->callJSFunction(token->getExecutorToken(nullptr),std::move(module),std::move(method),std::move(arguments->array));
}
Instance.cpp
void Instance::callJSFunction(ExecutorToken token,std::string&& module,std::string&& method,folly::dynamic&& params) { //调用nativeToJsBridge的callFunction方法 nativeToJsBridge_->callFunction(token,std::move(module),std::move(method),std::move(params)); }
NativeToJsBridge.cpp
void NativeToJsBridge::callFunction(
ExecutorToken executorToken,std::string&& module,std::string&& method,folly::dynamic&& arguments) {
int systraceCookie = -1;
#ifdef WITH_FBSYSTRACE
systraceCookie = m_systraceCookie++;
std::string tracingName = fbsystrace_is_tracing(TRACE_TAG_REACT_CXX_BRIDGE) ?
folly::to<std::string>("JSCall__",'_',method) : std::string();
SystraceSection s(tracingName.c_str());
FbSystraceAsyncFlow::begin(
TRACE_TAG_REACT_CXX_BRIDGE,tracingName.c_str(),systraceCookie);
#else
std::string tracingName;
#endif
runOnExecutorQueue(executorToken,[module = std::move(module),method = std::move(method),arguments = std::move(arguments),tracingName = std::move(tracingName),systraceCookie] (JSExecutor* executor) {
//调用executor的callFunction
// This is safe because we are running on the executor's thread: it won't
// destruct until after it's been unregistered (which we check above) and
// that will happen on this thread
executor->callFunction(module,arguments);
});
}
JSCExecutor.cpp
void JSCExecutor::callFunction(const std::string& moduleId,const std::string& methodId,const folly::dynamic& arguments) {
auto result = [&] {
try {
//调用m_callFunctionReturnFlushedQueueJS方法,并获取返回值(就是前面的queue里面的数据)
return m_callFunctionReturnFlushedQueueJS->callAsFunction({
Value(m_context,String::createExpectingAscii(m_context,moduleId)),Value(m_context,methodId)),Value::fromDynamic(m_context,std::move(arguments))
});
} catch (...) {
std::throw_with_nested(
std::runtime_error("Error calling function: " + moduleId + ":" + methodId));
}
}();
//调用原生代码
callNativeModules(std::move(result));
}
//m_invokeCallbackAndReturnFlushedQueueJS初始化如下
void JSCExecutor::bindBridge() throw(JSException) {
//获取js根对象
auto global = Object::getGlobalObject(m_context);
//获取js全局对象__fbBatchedBridge
auto batchedBridgeValue = global.getProperty("__fbBatchedBridge");
auto batchedBridge = batchedBridgeValue.asObject();
//__fbBatchedBridge的一个方法
m_callFunctionReturnFlushedQueueJS =
batchedBridge.getProperty("callFunctionReturnFlushedQueue").asObject();
//——fbBatchedBridge的一个方法
m_invokeCallbackAndReturnFlushedQueueJS = batchedBridge.getProperty("invokeCallbackAndReturnFlushedQueue").asObject();
//——fbBatchedBridge的一个方法
m_flushedQueueJS = batchedBridge.getProperty("flushedQueue").asObject();
//——fbBatchedBridge的一个方法
m_callFunctionReturnResultAndFlushedQueueJS = batchedBridge.getProperty("callFunctionReturnResultAndFlushedQueue").asObject();
}
__fbBatchedBridge是在BatchedBridge.js中定义好的全局对象,实际上是一个MessageQueue对象
网络返回js层
const MessageQueue = require('MessageQueue');
const BatchedBridge = new MessageQueue();
Object.defineProperty(global,'__fbBatchedBridge',{
configurable: true,value: BatchedBridge,});
module.exports = BatchedBridge;
MessageQueue.js中的callFunctionReturnFlushedQueue方法
callFunctionReturnFlushedQueue(module: string,method: string,args: Array<any>) { //执行方法 this.__callFunction(module,args); this.__callImmediates(); //将queue数组里面的信息返回JNI端 return this.flushedQueue(); }
__callFunction(module: string,args: Array<any>) { //module 取值为RCTDeviceEventEmitter //method 取值为emit const moduleMethods = this._callableModules[module]; const result = moduleMethods[method].apply(moduleMethods,args); Systrace.endEvent(); return result; }
参数如图所示:
这里调用了RCTDeviceEventEmitter的emit方法并传入了网络请求的response.
到这里response已经返回到js端了。