写点什么

React Native Android 混合开发实战教程,Android 入门你值得拥有

用户头像
Android架构
关注
发布于: 2021 年 11 月 05 日

<activity android:name="com.facebook.react.devsupport.DevSettingsActivity" />


提示:上述图片就是 RN 开发调试弹框中的Dev Settings功能,打开该功能会弹出上图的一个界面,这个界面就是 DevSettingsActivity。

第三步:指定要 ndk 需要兼容的架构(重要)

Android 不能同时加载多种架构的 so 库,现在很多 Android 第三方 sdks 对 abi 的支持比较全,可能会包含 armeabi, armeabi-v7a,x86, arm64-v8a,x86_64 五种 abi,如果不加限制直接引用会自动编译出支持 5 种 abi 的 APK,而 Android 设备会从这些 abi 进行中优先选择某一个,比如:arm64-v8a,但如果其他 sdk 不支持这个架构的 abi 的话就会出现 crash。如下图:



怎么解决呢:


app/gradle 文件中添加如下代码:


defaultConfig {....ndk {abiFilters "armeabi-v7a", "x86"}}


上述代码的意思是,限制打包的 so 库只包含armeabi-v7ax86。**[此过程所遇到的更多问题可查阅:React Native 与 Android 混合开发讲解的视频教程](


)**


可参考:[libgnustl_shared.so" is 32-bit instead of 64-bit](


)

3.创建 index.js 并添加你的 React Native 代码

通过上述两步,我们已经为 RNHybridAndroid 项目添加了 React Native 依赖,接下来我们来开发一些 JS 代码。


在 RNHybrid 目录下创建一个index.js文件并添加如下代码:


import { AppRegistry } from 'react-native';import App from './App';


AppRegistry.registerComponent('App1', () => App);


上述代码,AppRegistry.registerComponent('App1', () => App);目的是向 React Native 注册一个名为App1的组件,然后我会在第四步给大家介绍如何在 Android 中加载并显示出这个组件。


另外,在上述代码中我们引用了一个App.js文件:


import React, { Component } from 'react';import {Platform,StyleSheet,Text,View} from 'react-native';


type Props = {};export default class App extends Component<Props> {render() {return (<View style={styles.container}><Text style={styles.welcome}>this is App</Text></View>);}}


const styles = StyleSheet.create({container: {flex: 1,justifyContent: 'center',alignItems: 'center',backgroundColor: '#F5FCFF',},welcome: {fontSize: 20,textAlign: 'center',margin: 10,}});


这个App.js文件代表了我们 React Native 的一个页面,在这个页面中显示了this is App的文本内容。


以上就是为本次演示所添加的 React Native 代码,你也可以根据需要添加更多的 React Native 代码以及组件出来。

4. 为 React Native 创建一个 Activity 来作为容器

经过上述 3、4 步,我们已经为 RNHybridAndroid 项目添加了 React Native 依赖,并且创建一些 React Native 代码和注册了一个名为App1的组件,接下来我们来学习下如何在 RNHybridAndroid 项目中使用这个App1组件。

创建 RNPageActivity

首先我们需要创建一个 Activity 来作为 React Native 的容器,


public class RNPageActivity extends AppCompatActivity implements DefaultHardwareBackBtnHandler {private ReactRootView mReactRootView;private ReactInstanceManager mReactInstanceManager;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);


mReactRootView = new ReactRootView(this);mReactInstanceManager = ReactInstanceManager.builder().setApplication(getApplication()).setBundleAssetName("index.android.bundle").setJSMainModulePath("index").addPackage(new MainReactPackage()).setUseDeveloperSupport(BuildConfig.DEBUG).setInitialLifecycleState(LifecycleState.RESUMED).build();// 这个"App1"名字一定要和我们在 index.js 中注册的名字保持一致 AppRegistry.registerComponent()mReactRootView.startReactApplication(mReactInstanceManager, "App1", null);


setContentView(mReactRootView);}


@Overridepublic void invokeDefaultOnBackPressed() {super.onBackPressed();}}


参数说明


  • setBundleAssetName:打包时放在assets目录下的 JS bundle 包的名字,App release 之后会从该目录下加载 JS bundle;

  • setJSMainModulePath:JS bundle 中主入口的文件名,也就是我们上文中创建的那个index.js文件;

  • addPackage:向 RN 添加 Native Moudle,在上述代码中我们添加了new MainReactPackage()这个是必须的,另外,如果我们创建一些其他的 Native Moudle 也需要通过addPackage的方式将其注册到 RN 中。需要指出的是 RN 除了这个方法外,也提供了一个addPackages方法用于批量向 RN 添加 Native Moudle;

  • setUseDeveloperSupport:设置 RN 是否开启开发者模式(debugging,reload,dev memu),比如我们常用开发者弹框;

  • setInitialLifecycleState:通过这个方法来设置 RN 初始化时所处的生命周期状态,一般设置成LifecycleState.RESUMED就行,和下文讲的 Activity 容器的生命周期状态关联;

  • mReactRootView.startReactApplication:它的第一个参数是mReactInstanceManager,第二个参数是我们在index.js中注册的组件的名字,第三个参数接受一个Bundle来作为 RN 初始化时传递给 JS 的初始化数据,它的具体用法我会在**[React Android 混合开发讲解的视频教程](


)**中再具体的讲解;

在中AndroidManifest.xml注册一个 RNPageActivity

Android 系统要求,每一个要打开的 Activity 都要在AndroidManifest.xml中进行注册:


<activityandroid:name=".RNPageActivity"android:configChanges="keyboard|keyboardHidden|orientation|screenSize"android:windowSoftInputMode="adjustResize"android:theme="@style/Theme.AppCompat.Light.NoActionBar" />


上述代码中我们为RNPageActivity添加了一个@style/Theme.AppCompat.Light.NoActionBar类型的 theme,这也是 React Native UI 组件所要求的主题。

为 ReactInstanceManager 添加 Activity 的生命周期回调

一个 ReactInstanceManager 可以被多个 activities 或 fragments 共享,所以我们需要在 Activity 的生命周期中回调 ReactInstanceManager 的对于的方法。


@Overrideprotected void onPause() {super.onPause();


if (mReactInstanceManager != null) {mReactInstanceManager.onHostPause(this);}}


@Overrideprotected void onResume() {super.onResume();


if (mReactInstanceManager != null) {mReactInstanceManager.onHostResume(this, this);}}


@Overridepublic void onBackPressed() {if (mReactInstanceManager != null) {mReactInstanceManager.onBackPressed();} else {super.onBackPressed();}}


@Overrideprotected void onDestroy() {super.onDestroy();


if (mReactInstanceManager != null) {mReactInstanceManager.onHostDestroy(this);}if (mReactRootView != null) {mReactRootView.unmountReactApplication();}}


从上述代码中你会发现有个不属于 Activity 生命周期中的方法onBackPressed,添加它的目的主要是为了当用户单击手机的返回键之后将事件传递给 JS,如果 JS 消费了这个事件,Native 就不再消费了,如果 JS 没有消费这个事件那么 RN 会回调invokeDefaultOnBackPressed代码。


@Overridepublic void invokeDefaultOnBackPressed() {super.onBackPressed();}


**[此过程更细致的讲解可查阅:React Native 与 Android 混合开发讲解的视频教程](


)**

添加开发者菜单

在 RN 中有个很好用的工具开发者菜单,我们平时调试 RN 应用时对它的使用频率很高,接下来我们来为 RNHybridAndroid 添加开着菜单。


public boolean onKeyUp(int keyCode, KeyEvent event) {if (getUseDeveloperSupport()) {if (keyCode == KeyEvent.KEYCODE_MENU) {//Ctrl + M 打开 RN 开发者菜单 mReactInstanceManager.showDevOptionsDialog();return true;}}return super.onKeyUp(keyCode, event);}


通过上代码即可监听Ctrl + M来打开 RN 开发者菜单。



另外,RN 也提供了双击 R 来快速加载 JS 的功能,通过如下代码即可打开该功能:


public boolean onKeyUp(int keyCode, KeyEvent event) {if (getUseDeveloperSupport()) {if (keyCode == KeyEvent.KEYCODE_MENU) {//Ctrl + M 打开 RN 开发者菜单 mReactInstanceManager.showDevOptionsDialog();return true;}boolean didDoubleTapR = Assertions.assertNotNull(mDoubleTapReloadRecognizer).didDoubleTapR(keyCode, getCurrentFocus());if (didDoubleTapR) {//双击 R 重新加载 JSmReactInstanceManager.getDevSupportManager().handleReloadJS();return true;}}return super.onKeyUp(keyCode, event);}


**[此过程更细致的讲解可查阅:React Native 与 Android 混合开发讲解的视频教程](


)**

使用 ReactActivity 来作为 RN 容器

在上述的代码中我们都是通过ReactInstanceManager来创建和加载 JS 的,然后重写了 Activity 的生命周期来对ReactInstanceManager进行回调,另外,重写了onKeyUp来启用开发者菜单等功能。


另外,查看 RN 的源码你会发现在 RN sdk 中有个叫ReactActivity的 Activity,该 Activity 是 RN 官方封装的一个 RN 容器。另外,在通过react-native init命令初始化的一个项目中你会发现有个MainActivity是继承ReactActivity的,接下来我们就来继承ReactActivity来封装一个 RN 容器。


public class ReactPageActivity extends ReactActivity implements IJSBridge{/**


  • Returns the name of the main component registered from JavaScript.

  • This is used to schedule rendering of the component.*/@Overrideprotected String getMainComponentName() {return "App1";}}


另外,我们需要实现一个MainApplication并添加如下代码:


public class MainApplication extends Application implements ReactApplication {


private final ReactNativeHost mReactNativeHost = new ReactNativeHost(this) {@Overridepublic boolean getUseDeveloperSupport() {return BuildConfig.DEBUG;}


@Overrideprotected List<ReactPackage> getPackages() {return Arrays.<ReactPackage>asList(new MainReactPackage());}


@Overrideprotected String getJSMainModuleName() {return "index";}};


@Overridepublic ReactNativeHost getReactNativeHost() {return mReactNativeHost;}


@Overridepublic void onCreate() {super.onCreate();SoLoader.init(this, /* native exopackage */ false);}}


上述代码的主要作用是为ReactActivity提供ReactNativeHost,查看源码你会发现在ReactActivity中使用了ReactActivityDelegate,在ReactActivityDelegate中会用到MainApplication中提供的ReactNativeHost


protected ReactNativeHost getReactNativeHost() {return ((ReactApplication) getPlainActivity().getApplication()).getReactNativeHost();}


另外实现了MainApplication之后需要在AndroidManifest.xml中添加MainApplication


<applicationandroid:name=".MainApplication"android:allowBackup="true"android:icon="@mipmap/ic_l


《Android学习笔记总结+最新移动架构视频+大厂安卓面试真题+项目实战源码讲义》
浏览器打开:qq.cn.hn/FTe 免费领取
复制代码


auncher"android:label="@string/app_name"android:roundIcon="@mipmap/ic_launcher_round"android:supportsRtl="true"android:theme="@style/AppTheme">...


以上就是通过继承ReactActivity的方式来作为 RN 容器的。


那么这两种方式各有什么特点:


  • 通过ReactInstanceManager的方式:灵活,可定制性强;

  • 通过继承ReactActivity的方式:简单,可定制性差;

用户头像

Android架构

关注

还未添加个人签名 2021.10.31 加入

还未添加个人简介

评论

发布
暂无评论
React Native Android混合开发实战教程,Android入门你值得拥有