在使用 react-native 的时候,有时候我们需要使用自己定义的OkHttpClient。例如:
- 使用stetho抓包的时候需要在 OkHttpClient 中加入 StethoInterceptor 拦截器
- 使用自签名的 https 证书的时候需要在 OkHttpClient 中使用直接SocketFactory
- ……
在 react-native 的 0.42 和之前的版本中,我们可以通过
OkHttpClientProvider.replaceOkHttpClient(client)
替换系统默认的 OkHttpClient ,但0.43 和之后的版本就不行了。未来解决一个 bug ,0.43 之后的版本中,NetworkingModule 不再通过OkHttpClientProvider.getOkHttpClient()
来获取 OkHttpClient 对象对象,而是 通过 OkHttpClientProvider.createClient()
来获取 OkHttpClient 对象(https://github.com/facebook/react-native/commit/0a71f48b1349ed09bcb6e76ba9ff8eb388518b15#diff-f8703d50cf5af4c06824e2928dddb500)。
查看 NetworkingModule.java 的源码可以发现,NetworkingModule 是一个 final 类,我们无法通过继承来重写 NetworkingModule 类。而且 NetworkingModule 拥有自定义 OkHttpClient 的构造器,可惜是包级的。
/** * @param context the ReactContext of the application * @param defaultUserAgent the User-Agent header that will be set for all requests where the * caller does not provide one explicitly * @param client the {@link OkHttpClient} to be used for networking */
/* package */ NetworkingModule(
ReactApplicationContext context,@Nullable String defaultUserAgent,OkHttpClient client) {
this(context,defaultUserAgent,client,null);
}
研究之后发现,其实可以创建同样的包来使用这个包级的构造器。
package com.facebook.react.modules.network;
import com.facebook.react.bridge.ReactApplicationContext;
import okhttp3.OkHttpClient;
public class NetworkingModuleCreateUtil {
public static NetworkingModule create(ReactApplicationContext reactApplicationContext) {
//可以在这里对OkHttpClient添加自己的设置,例如添加ssl的自签名证书
OkHttpClient okHttpClient = OkHttpClientProvider.getOkHttpClient();
return new NetworkingModule(reactApplicationContext,null,okHttpClient);
}
}
然后重写 MainReactPackage 替换 NetworkingModule 实例
import com.facebook.react.animated.NativeAnimatedModule;
import com.facebook.react.bridge.ModuleSpec;
import com.facebook.react.bridge.NativeModule;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.modules.accessibilityinfo.AccessibilityInfoModule;
import com.facebook.react.modules.appstate.AppStateModule;
import com.facebook.react.modules.camera.CameraRollManager;
import com.facebook.react.modules.camera.ImageEditingManager;
import com.facebook.react.modules.camera.ImageStoreManager;
import com.facebook.react.modules.clipboard.ClipboardModule;
import com.facebook.react.modules.datepicker.DatePickerDialogModule;
import com.facebook.react.modules.dialog.DialogModule;
import com.facebook.react.modules.fresco.FrescoModule;
import com.facebook.react.modules.i18nmanager.I18nManagerModule;
import com.facebook.react.modules.image.ImageLoaderModule;
import com.facebook.react.modules.intent.IntentModule;
import com.facebook.react.modules.location.LocationModule;
import com.facebook.react.modules.netinfo.NetInfoModule;
import com.facebook.react.modules.network.NetworkingModule;
import com.facebook.react.modules.network.NetworkingModuleCreateUtil;
import com.facebook.react.modules.permissions.PermissionsModule;
import com.facebook.react.modules.share.ShareModule;
import com.facebook.react.modules.statusbar.StatusBarModule;
import com.facebook.react.modules.storage.AsyncStorageModule;
import com.facebook.react.modules.timepicker.TimePickerDialogModule;
import com.facebook.react.modules.toast.ToastModule;
import com.facebook.react.modules.vibration.VibrationModule;
import com.facebook.react.modules.websocket.WebSocketModule;
import com.facebook.react.shell.MainPackageConfig;
import com.facebook.react.shell.MainReactPackage;
import java.util.Arrays;
import java.util.List;
import javax.inject.Provider;
public class NewMainReactPackage extends MainReactPackage {
private MainPackageConfig mConfig;
public NewMainReactPackage() {
super();
}
@Override
public List<ModuleSpec> getNativeModules(final ReactApplicationContext context) {
return Arrays.asList(
new ModuleSpec(AccessibilityInfoModule.class,new Provider<NativeModule>() {
@Override
public NativeModule get() {
return new AccessibilityInfoModule(context);
}
}),new ModuleSpec(AppStateModule.class,new Provider<NativeModule>() {
@Override
public NativeModule get() {
return new AppStateModule(context);
}
}),new ModuleSpec(AsyncStorageModule.class,new Provider<NativeModule>() {
@Override
public NativeModule get() {
return new AsyncStorageModule(context);
}
}),new ModuleSpec(CameraRollManager.class,new Provider<NativeModule>() {
@Override
public NativeModule get() {
return new CameraRollManager(context);
}
}),new ModuleSpec(ClipboardModule.class,new Provider<NativeModule>() {
@Override
public NativeModule get() {
return new ClipboardModule(context);
}
}),new ModuleSpec(DatePickerDialogModule.class,new Provider<NativeModule>() {
@Override
public NativeModule get() {
return new DatePickerDialogModule(context);
}
}),new ModuleSpec(DialogModule.class,new Provider<NativeModule>() {
@Override
public NativeModule get() {
return new DialogModule(context);
}
}),new ModuleSpec(FrescoModule.class,new Provider<NativeModule>() {
@Override
public NativeModule get() {
return new FrescoModule(context,true,mConfig != null ? mConfig.getFrescoConfig() : null);
}
}),new ModuleSpec(I18nManagerModule.class,new Provider<NativeModule>() {
@Override
public NativeModule get() {
return new I18nManagerModule(context);
}
}),new ModuleSpec(ImageEditingManager.class,new Provider<NativeModule>() {
@Override
public NativeModule get() {
return new ImageEditingManager(context);
}
}),new ModuleSpec(ImageLoaderModule.class,new Provider<NativeModule>() {
@Override
public NativeModule get() {
return new ImageLoaderModule(context);
}
}),new ModuleSpec(ImageStoreManager.class,new Provider<NativeModule>() {
@Override
public NativeModule get() {
return new ImageStoreManager(context);
}
}),new ModuleSpec(IntentModule.class,new Provider<NativeModule>() {
@Override
public NativeModule get() {
return new IntentModule(context);
}
}),new ModuleSpec(LocationModule.class,new Provider<NativeModule>() {
@Override
public NativeModule get() {
return new LocationModule(context);
}
}),new ModuleSpec(NativeAnimatedModule.class,new Provider<NativeModule>() {
@Override
public NativeModule get() {
return new NativeAnimatedModule(context);
}
}),new ModuleSpec(NetworkingModule.class,new Provider<NativeModule>() {
@Override
public NativeModule get() {
//关键在这里 把 new NetworkingModule(context) 替换成NetworkingModuleCreateUtil.create(context);
return NetworkingModuleCreateUtil.create(context);
}
}),new ModuleSpec(NetInfoModule.class,new Provider<NativeModule>() {
@Override
public NativeModule get() {
return new NetInfoModule(context);
}
}),new ModuleSpec(PermissionsModule.class,new Provider<NativeModule>() {
@Override
public NativeModule get() {
return new PermissionsModule(context);
}
}),new ModuleSpec(ShareModule.class,new Provider<NativeModule>() {
@Override
public NativeModule get() {
return new ShareModule(context);
}
}),new ModuleSpec(StatusBarModule.class,new Provider<NativeModule>() {
@Override
public NativeModule get() {
return new StatusBarModule(context);
}
}),new ModuleSpec(TimePickerDialogModule.class,new Provider<NativeModule>() {
@Override
public NativeModule get() {
return new TimePickerDialogModule(context);
}
}),new ModuleSpec(ToastModule.class,new Provider<NativeModule>() {
@Override
public NativeModule get() {
return new ToastModule(context);
}
}),new ModuleSpec(VibrationModule.class,new Provider<NativeModule>() {
@Override
public NativeModule get() {
return new VibrationModule(context);
}
}),new ModuleSpec(WebSocketModule.class,new Provider<NativeModule>() {
@Override
public NativeModule get() {
return new WebSocketModule(context);
}
}));
}
}
最后,使用在 ReactApplication 中 NewMainReactPackage 替换 MainReactPackage:
@Override
protected List<ReactPackage> getPackages() {
List<ReactPackage> packages = new ArrayList<>();
packages.add(new NewMainReactPackage());
return packages;
}
就可以使用自己的 OkHttpClient 了。