在macOS系统使用React Native的踩坑过程
最近做公司项目时使用到了React Native,首先需要在公司电脑上配置React Native的开发环境。公司电脑是mac本,那就按照React Native中文网站一步步配置macOS开发平台的开发环境。中间遇到了很多问题,总结一下解决方法把它们一一记录下来。
问题1:必须安装的依赖有:Node、Watchman 和 React Native 命令行工具以及 JDK 和 Andriod Studio。官方推荐使用Homebrew来安装 Node 和 Watchman,安装Homebrew的命令是:
/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)" 。
需要访问github网站,但是由于安全性的原因,公司电脑禁止访问github网站,导致安装Homebrew这一步就进行不下去了,在这个地方折腾了很久,后来经过跟同事讨论找到了一种解决方案。从已经安装好react native开发环境的另外一台电脑上拷贝以下文件
/usr/local/bin/brew
/usr/local/share/doc/homebrew
/usr/local/share/man/man1/brew.1
/usr/local/share/zsh/site-functions/_brew
/usr/local/etc/bash_completion.d/brew
/usr/local/Homebrew
到公司电脑上。这样brew命令便可正常使用,算是曲线救国吧!
问题2:由于之前已经安装过watchman,所以再次通过brew来安装时有冲突。执行brew install watchman
提示:Warning: watchman 4.9.0 is already installed, it's just not linked. You can use brew link watchman
to link this version.
解决方案是:先执行brew uninstall watchman,再执行brew install --HEAD watchman,watchman安装成功。
问题3:通过react-native start启动server时,提示8081端口被占用。
解决方案:修改端口号的方法,参考文章:https://www.jianshu.com/p/ef00ec56507c
问题4:编译项目时提示jcenter中的依赖包下载超时(还是因为公司网络安全策略问题)
解决方法是:在根目录下的build.gradle中修改jcenter的url
222.png
问题5:添加环境变量时需要注意,.bash_profile添加多个PATH时,后面的PATH在最前面都要加上$PATH:,否则会覆盖前面的PATH。
屏幕快照 2018-10-09 下午4.58.04.png
如何实现android原生模块和react native函数的互调?
问题6:react native调用Android原生模块
1.我们首先来创建一个原生模块。一个原生模块是一个继承了ReactContextBaseJavaModule的 Java 类,它可以实现一些 JavaScript 所需的功能。
例如:public class ToastModule extends ReactContextBaseJavaModule
2.要导出一个方法给 JavaScript 使用,Java 方法需要使用注解@ReactMethod。方法的返回类型必须为void。
3.在 Java 这边要做的最后一件事就是注册这个模块。我们需要在应用的 Package 类的createNativeModules方法中添加这个模块。如果模块没有被注册,它也无法在 JavaScript 中被访问到。
4.这个 package 需要在MainApplication.java文件的getPackages方法中提供。这个文件位于你的 react-native 应用文件夹的 android 目录中。
5.原生模块还支持一种特殊的参数——回调函数。它提供了一个函数来把返回值传回给 JavaScript。
问题7:Android原生模块调用react native函数
原生模块可以在没有被调用的情况下往 JavaScript 发送事件通知。最简单的办法就是通过RCTDeviceEventEmitter,这可以通过ReactContext来获得对应的引用,像这样:
...
private void sendEvent(ReactContext reactContext,
String eventName,
@Nullable WritableMap params) {
reactContext
.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
.emit(eventName, params);
}
...
WritableMap params = Arguments.createMap();
...
sendEvent(reactContext, "keyboardWillShow", params);
问题8:在android手机上运行react-native项目时,报错:unable to load script from assets 'index.android bundle' , make sure your bundle is packaged correctly or youu're runing a packager server。
解决方案:
第一步:在 android/app/src/main 目录下创建一个 assets空文件夹
第二步:在项目根目录下执行下面这段命令
react-native bundle --platform android --dev false --entry-file index.js --bundle-output android/app/src/main/assets/index.android.bundle --assets-dest android/app/src/main/res/
会发现 assets文件夹下生成index.android.bundle文件
第三步:重新执行 react-native run-android
总结:这个index.android.bundle毫无疑问就是用来调用原生控件的js脚本,每次当你改变了index.js,你都需要使用上面的代码片段,来及时的更新index.android.bundle,然后打包才可以把新的index.js应用上,所以当没有index.android.bundle文件时,RN是无法运行的。
问题9:React Native版本无法升级到0.20.1以上版本的原因
Android项目默认的依赖包的源jcenter(),打开网址https://bintray.com/bintray/jcenter/com.facebook.react:react-native/view,
发现jcenter()上并不包含最新版的React Native(官方只更新到0.20.1)。
在React Native项目中,Android 项目需要在android/app/build.gradle文件中,添加React Native依赖:compile "com.facebook.react:react-native:+" // From node_modules,默认使用的是node_modules/react-native/android/com/facebook/react/react-native目录下的react native版本。然而Android原生项目中并不存在node_modules目录,如何才能引用到最新的react native版本呢?经过各种尝试,终于找到了一种解决方案。
将node_modules/react-native/android/com/facebook/react/react-native目录下下载的react-native-0.xx.x.aar包加入到Android工程的libs目录下,并引用该aar包,但是你编译时会发现报错提示你缺少XXX等等,为什么呢?这是因为这个aar中还依赖了其它的jar or aar,所以我们需要把这些包也给implementation进来,我们看下具体有哪些包?打开node_modules/react-native/android/com/facebook/react/react-native中的pom文件,里面就是所有的依赖,在build.gradle中配置依赖如下:
implementation 'javax.inject:javax.inject:1'
implementation 'com.android.support:appcompat-v7:26.1.0'
implementation 'com.facebook.fbui.textlayoutbuilder:textlayoutbuilder:1.0.0'
implementation 'com.facebook.fresco:fresco:1.3.0'
implementation 'com.facebook.fresco:imagepipeline-okhttp3:1.3.0'
implementation 'com.facebook.soloader:soloader:0.1.0'
implementation 'com.google.code.findbugs:jsr305:3.0.0'
implementation 'com.squareup.okhttp3:okhttp:3.6.0'
implementation 'com.squareup.okhttp3:okhttp-urlconnection:3.6.0'
implementation 'com.squareup.okio:okio:1.13.0'
implementation 'org.webkit:android-jsc:r174650'
先总结到这里,后续开发中遇到新的问题再更新。