@Override
protected 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);
}
@Override
public 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
中进行注册:
上述代码中我们为
RNPageActivity
添加了一个@style/Theme.AppCompat.Light.NoActionBar
类型的theme,这也是React Native UI组件所要求的主题。
为ReactInstanceManager添加Activity的生命周期回调
一个 ReactInstanceManager可以被多个activities或fragments共享,所以我们需要在Activity的生命周期中回调ReactInstanceManager的对于的方法。
@Override
protected void onPause() {
super.onPause();
if (mReactInstanceManager != null) {
mReactInstanceManager.onHostPause(this);
}
}
@Override
protected void onResume() {
super.onResume();
if (mReactInstanceManager != null) {
mReactInstanceManager.onHostResume(this, this);
}
}
@Override
public void onBackPressed() {
if (mReactInstanceManager != null) {
mReactInstanceManager.onBackPressed();
} else {
super.onBackPressed();
}
}
@Override
protected void onDestroy() {
super.onDestroy();
if (mReactInstanceManager != null) {
mReactInstanceManager.onHostDestroy(this);
}
if (mReactRootView != null) {
mReactRootView.unmountReactApplication();
}
}
从上述代码中你会发现有个不属于Activity生命周期中的方法onBackPressed
,添加它的目的主要是为了当用户单击手机的返回键之后将事件传递给JS,如果JS消费了这个事件,Native就不再消费了,如果JS没有消费这个事件那么RN会回调invokeDefaultOnBackPressed
代码。
@Override
public 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 重新加载JS
mReactInstanceManager.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.
*/
@Override
protected String getMainComponentName() {
return “App1”;
}
}
另外,我们需要实现一个MainApplication
并添加如下代码:
public class MainApplication extends Application implements ReactApplication {
private final ReactNativeHost mReactNativeHost = new ReactNativeHost(this) {
@Override
public boolean getUseDeveloperSupport() {
return BuildConfig.DEBUG;
}
@Override
protected List getPackages() {
return Arrays.asList(
new MainReactPackage()
);
}
@Override
protected String getJSMainModuleName() {
return “index”;
}
};
@Override
public ReactNativeHost getReactNativeHost() {
return mReactNativeHost;
}
@Override
public 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
:
…
以上就是通过继承ReactActivity
的方式来作为RN容器的。
那么这两种方式各有什么特点:
- 通过
ReactInstanceManager
的方式:灵活,可定制性强; - 通过继承
ReactActivity
的方式:简单,可定制性差;
此过程更细致的讲解可查阅:React Native与Android 混合开发讲解的视频教程
5. 运行React Native
经过上述的步骤,我们已经完成了对一个现有Android项目RNHybridAndroid添加了RN,并且通过两种方式分别创建了一个RNPageActivity
与ReactPageActivity
的Activity来加载我们在JS中注册的名为App1
的RN 组件。
接下来我们来启动RN服务器,运行RNHybridAndroid项目打开RNPageActivity
或ReactPageActivity
来查看效果:
npm start
在RNHybrid
的根目录运行上述命令,来启动一个RN本地服务:
然后我们打开AndroidStudio,点击运行按钮或者通过快捷键Ctrl+R
来将RNHybridAndroid
安装到模拟器上:
6. 添加更多React Native的组件
我们可以根据需要添加更多的React Native的组件:
import { AppRegistry } from ‘react-native’;
import App from ‘./App’;
import App2 from ‘./App2’;
AppRegistry.registerComponent(‘App1’, () => App);
AppRegistry.registerComponent(‘App2’, () => App);
然后,在Native中根据需要加载指定名字的RN组件即可。
7. 调试、打包、发布应用
调试
调试这种混合的RN应用和调试一个纯RN应用时一样的,都是通过上文中说讲到的RN 开发者菜单
,另外搭建也可以通过学习React Native技术精讲与高质量上线APP开发课程来掌握更多RN调试的技巧。
打包
虽让,通过上述步骤,我们将RN和我们的RNHybridAndroid项目做了融合,但打包RNHybridAndroid你会发现里面并不包含JS部分的代码,如果要将JS代码打包进Android Apk包中,可以通过如下命令:
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数Android工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点,真正体系化!
由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新
如果你觉得这些内容对你有帮助,可以添加V获取:vip204888 (备注Android)
更多Android高级工程师进阶学习资料
进阶学习视频
附上:我们之前因为秋招收集的二十套一二线互联网公司Android面试真题(含BAT、小米、华为、美团、滴滴)和我自己整理Android复习笔记(包含Android基础知识点、Android扩展知识点、Android源码解析、设计模式汇总、Gradle知识点、常见算法题汇总。)
里面包含不同方向的自学编程路线、面试题集合/面经、及系列技术文章等,资源持续更新中…
一个人可以走的很快,但一群人才能走的更远。不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎扫码加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
笔记(包含Android基础知识点、Android扩展知识点、Android源码解析、设计模式汇总、Gradle知识点、常见算法题汇总。)
[外链图片转存中…(img-cI22fp1b-1712662756242)]
里面包含不同方向的自学编程路线、面试题集合/面经、及系列技术文章等,资源持续更新中…
一个人可以走的很快,但一群人才能走的更远。不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎扫码加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
[外链图片转存中…(img-Nv4esAuo-1712662756243)]