此文已由作者王宇飞授权网易云社区发布。
欢迎访问网易云社区,了解更多网易技术产品运营经验。
React Native 出来已经有相当长一段时间了,相比于 H5 页面令人揪心的性能, React Native 在性能上接近原生代码的表现确实让人惊艳。大白话来说,React Native 用 JavaScript 能完成传统原生代码的功能,实现了跨平台开发,更重要的是对代码的动态更新的意义。之前听说阿里在双11活动中应用到了 React Native 的相关技术,并且提出了无线电商动态化解决方案 Weex,暂且不论外界对于 Weex 是如何评价的,现在倒是时候尝试一下 React Native 了。
React Native 对于 Android 的友好度远不及 iOS,对于 Windows 平台的友好度也远不及 Linux 和 Mac OS。在使用过程中也是坑坑洼洼无数,考虑到我厂不少 Android 开发童鞋使用的平台是 Windows,所以后面的内容两个平台都会提到。
大部分内容都是基于官方的文档,但是官方文档目前在很多地方并不完善,有坑的地方不少,我会把遇到的坑都特别说明出来。
JDK(基本废话...)
Android SDK(同上,但最好将 ANDROID_HOME 写入 path 中,不写也行,不过以后会略微麻烦)
Node.js (官方要求 4.0 以上版本) Windows 下还要注意配置环境变量
后文中不少操作执行的时间都比较长,需要耐心等...
使用起来很简单,其实就是官方文档中列出的三步:
npm install -g react-native-cli
react-native init AwesomeProject
react-native run-android
简单来说就是:安装 react-native 命令行工具 -> 初始化项目 -> 运行
Windows 下注意下面提到的 “坑2”
坑1:【网络环境】: 由于“众所周知”的原因,各个步骤都建议自备梯子
坑2:Windows 下 Packager 的启动 根据官方的说法,Packager 是一个模块管理者,当前阶段直观来看,它使得 App 在调试阶段从远端(也就是你的电脑)获取需要加载的 js。如果在 Mac 下,执行 react-native run-android 后 Packager 会自动运行,而在 Win 下则不会。所以,切记!!!【 Win 里在执行 run-android 之前务必先在项目目录下执行 react-native start】
对应到例子中就是:
cd AwesomeProject
react-native start
如下图即为启动成功:
要保持 Packager 一直运行,所以,不能关闭当前 CMD 窗口。
坑3:调试服务器配置 通常首次运行会失败出现红色屏幕,提示 Can't find variable: __fbBatchedBridge 或 unable to download js bundle。
出错的主要原因在于 App 无法与 Packager 通信,比如,公司电脑接入公司有线网络,调试用的真机接入 Netease Wi-Fi,默认的配置下是无法调试的,需要在 Packager 已经成功启动的前提下,在红色屏幕出现时点击菜单按键或者摇动手机,出现菜单后选择 Dev Settings,进入 Debug server host & port for device,输入 <电脑IP>:8081,然后返回,然后再次进入菜单选 Reload JS。有的时候即使这样也不会成功,请检查电脑的 8081 端口是否被其他进程占用。
坑4: 注册设置 Activity 摇手机出现菜单后点击 Dev Settings 还有可能 Crash,这是因为还需要在 Manifest 设置界面对应的 Activity :
<activity android:name="com.facebook.react.devsupport.DevSettingsActivity" />
首先,集成 React Native 需要 API 16+
这才是实际使用中最常用到方式,毕竟依靠纯 React Native 实现一个 App 的情形并不多。
首先,在 app.gradle 中引入依赖:
compile 'com.facebook.react:react-native:0.20.0' (写这篇文章时的最新版本)
在 Manifest 中声明权限:(调试用,如果实际不需联网可在发布时去除这个权限)
<uses-permission android:name="android.permission.INTERNET" />
然后在需要使用 React Native 的地方做如下处理:
01 public class MainActivity extends AppCompatActivity implements DefaultHardwareBackBtnHandler { 02 03 private ReactInstanceManager mReactInstanceManager; 04 05 @Override 06 protected void onCreate(Bundle savedInstanceState) { 07 super.onCreate(savedInstanceState); 08 setContentView(R.layout.activity_main); 09 if (Build.VERSION.SDK_INT >= 23 && !Settings.canDrawOverlays(this)) { 10 Intent serviceIntent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION); 11 startActivity(serviceIntent); 12 finish(); 13 } else { 14 ReactRootView reactRootView = (ReactRootView) findViewById(R.id.react_view); 15 mReactInstanceManager = ReactInstanceManager.builder() 16 .setApplication(getApplication()) 17 .setBundleAssetName("index.android.bundle") 18 .setJSMainModuleName("index.android") 19 .addPackage(new MainReactPackage()) 20 .setUseDeveloperSupport(BuildConfig.DEBUG) // set DEBUG to true!!! 21 .setInitialLifecycleState(LifecycleState.RESUMED) 22 .build(); 23 reactRootView.startReactApplication(mReactInstanceManager, "DemoApp", null); 24 } 25 } 26 27 @Override 28 public void invokeDefaultOnBackPressed() { 29 super.onBackPressed(); 30 } ...
DefaultHardwareBackBtnHandler 接口以及其 invokeDefaultOnBackPressed 用于处理返回按键按下对 React Native 层面的影响,如果 React Native 界面不需要对返回事件作特殊处理,直接执行系统返回事件即可。
类似于 WebView, React Native 用于显示界面的控件为 ReactRootView,其本质上为 FrameLayout。
【第 9 - 13 行代码】由于 Android 6.0+ 增强了权限管理,所以在 API 23+ 时需要额外请求 OVERLAY_PERMISSION,在弹出的界面中将当前应用设为“允许”,然后再次启动。否则就没办法显示红色的错误提示并且 crash。这个问题在 API 22- 中不存在。这个处理也仅仅针对调试环境,正式环境可以去掉。
ReactInstanceManager 用于管理 CatalystInstance 对象, CatalystInstance 对象简单来说就是提供了 JavaScript 调用以及通过 JavaScript 调用本地 Java 方法的环境的对象, CatalystInstance 本身是一个接口。由于 ReactInstanceManager 管理着对象的生命周期,因此它需要与其所在的 Activity/Fragment 生命周期相关连,如下代码是必须的,类似的还有 onResume, onBackPressed 等。
@Overrideprotected void onPause() { super.onPause(); if (mReactInstanceManager != null) { mReactInstanceManager.onPause(); } }
最后,通过 startReactApplication 启动相应的 React Application,第二个参数为 React JS 模块名。
Java 代码写完以后,进入项目的根目录,依次执行:
npm init
npm install --save react-native
curl -o .flowconfig https://raw.githubusercontent.com/facebook/react-native/master/.flowconfig
整个过程耗时比较长,其中npm init 执行时需要输入一些信息,官方并没有特殊要求,大部分默认即可。
完成后,打开 packge.json, 删除 scripts 下的内容,并填入:
"start": "node_modules/react-native/packager/packager.sh"
【注意】 Windows 下不需要这一步
然后在根目录下创建一个名为 index.anroid.js 的 js 文件,填入如下 示例内容:
'use strict'; var React = require('react-native'); var { Text, View } = React;class DemoApp extends React.Component { render() { return ( <View style={styles.container}> <Text style={styles.hello}>React TextView</Text> </View> ) } } var styles = React.StyleSheet.create({ container: { flex: 1, justifyContent: 'center', }, hello: { fontSize: 25, textAlign: 'center', margin: 10, }, }); React.AppRegistry.registerComponent('DemoApp', () => DemoApp);
一切 OK 后,进入 Android Studio, 在 Terminal 中输入 npm start (Mac OS) 或者 react-native start(Windows),点击运行,第一次设置好调试服务器的 IP 与端口, Reload JS, 即可成功运行,如图。
坑5:BuildConfig.DEBUG 这个坑折腾了足足了半天的时间。官方的示例中直接使用了 setUseDeveloperSupport(BuildConfig.DEBUG) 并没有说明其实他们的 demo 已经重写了 DEBUG 的值,默认 BuildConfig.DEBUG 的值是 false,也就是关闭调试。如果直接按上面的代码实现,在出现诸如 Can't find variable: __fbBatchedBridge 错误时 App 会直接 Crash,没有机会修改 Debug Server 的 IP 和端口。所以,在调用 setUseDeveloperSupport 时可以直接传入 true 或者重写 DEBUG 的值。
坑6: Windows 下的 Visual Studio 在 Windows 下执行 npm install --save react-native 时有一系列的编译操作,需要诸如 VCBuild.exe 等程序, 为了保证执行成功, 需要安装 .NET Framework SDK 或者是 Visual Studio, 并且保证相关编译程序配置的正确。 出于配置上方便的考虑,推荐直接安装一个 Visual Studio =。=
7 Windows 下的 curl Windows 下默认没有 curl,需要从 curl 官网下载一个 curl.exe 放入 System32 目录下。执行 curl 时还可能会出现证书相关的错误,可以尝试 curl -k -o .....
开发阶段,App 可以通过 Packager 从调试服务器获取 js 等资源,App 发布时,js 等资源需要打入 apk 中,这个过程自然需要些额外工作。
如果 React Native 是通过 react-native init <Project Name> 生成的,正常情况下项目中会存在 react.gradle(如果没有,请升级 react-native 版本,当前 master 上的版本已经没有什么问题了,升级方法这里就不说了)。然后,直接执行 ./gradlew assembleRelase 即可。
如果 React Native 是集成到之前的原生项目中的,那项目中并不会存在 react.gradle 这个文件,这个时候就需要手动生成 assets 目录和 bundle 文件,从而将 js 等相关资源文件打入 apk 之中。目前这些可以通过插件或者命令行的方式进行,官方倾向于使用 react-native bundle。在开发完毕所有功能测试通过后,在 Android Studio 的 Terminal 中执行如下命令:
创建 assets 目录
mkdir -p app/src/main/assets
执行 react-native bundle,生成 bundle 文件,执行相关操作
react-native bundle --platform android --dev false --entry-file index.android.js --bundle-output app/src/main/assets/index.android.bundle --assets-dest app/src/main/res/
一切成功的话在 assets 下出现 bundle 文件。
最后,在配置好 gradle 中相关签名信息后, 执行./gradlew assembleRelase 获得发布包
react-native bundle 的两个重要参数:
--dev 设置 DEV 标记,发布时置为 false
--minify 是否对 js bundle 混淆
React Native 目前仍处在 0.xx 的版本中,未来的空间还很大,目前很多商业上的成功应用也说明了它的价值。但是其本身也并不完善,在写这篇文章的过程中就遇到了多次问题,如果有一些难以解决的问题,可以去 React Native 在 Github 上的 issue 里看看。
本文只是简单介绍了 React Native Android 的尝试过程,并没有涉及更深的领域和 React 的具体语法功能等。大家可以从下面的官方文档获取更多的信息。
默认情况下 React Native 是没有办法直接实现远程动态更新代码的,但是好消息是微软推出了 CodePush,有兴趣的话可以继续研究。
时间仓促加之水平有限,如果有任何错误欢迎大家批评指正。
网易云免费体验馆,0成本体验20+款云产品!
更多网易技术、产品、运营经验分享请点击。
相关文章:
【推荐】 JAVA虚拟机的类加载机制
【推荐】 如何开发一个可运维系统的一点体会