本篇博客仅作个人记录,如有错误大佬们欢迎提醒、评论、以及交流ReactNative技术。
我查看了许多博客,发现大多都写的比较简练,我就来结合自身的经验做个梳理和总结,帮助小白们加深一下对ReactNative+Android混合开发的理解。
这里说的混合开发与官网上说的【集成到现有原生应用】存在区别,一个是以原有的Android项目为基础,在此之上某一两个页面或业务流程用ReactNative。
而本博客要说的是在默认ReactNative项目的基础之上添加新的Android原生代码或者说原生页面。
相信大多数利用ReactNative开发的小伙伴们和我一样是前端出身,但是又对App感兴趣,所以入坑了ReactNative (说实话确实坑)。在此我会用一些前端的情况做类比,便于大家理解。
场景:ReactNative开发的App,无法完全满足业务需求,需要将第三方Android原生demo植入ReactNative项目中。
分析:从文件结构上看ReactNative项目在构建之初是一个单页面的App,利用了JavaScript构建的页面(实际上准确说并不是;RN是利用了桥接技术调用宿主平台的绘图API进行UI层的绘制,具体实现原理可以看官网的文档...这里先姑且这么说。这与uniapp等直接利用浏览器内核作为运行时的开发技术有着本质区别)其外在表现形式类似于前端的SPA模式,页面变化但不打开新的html页面。当用户进行页面跳转时,ReactNative其实是利用了 【React Navigation】 这个第三方库进行页面动画的绘制,从而达到了页面跳转的显示效果。但是这与传统原生开发时利用Intent进行Activity容器之间的跳转存在本质区别。(简单来说传统android开发一个Activity就是一个页面)
思考:既然默认的ReactNative可以算是一个单页面应用,那我们能不能给它加上一些原生的Activity容器,再通过一些操作让它从默认的Activiy上跳转到新的Activity上呢?类似于通过我这个SPA,在浏览器上打开一个新的标签页呢?
那就试试
第一步:我们要先看明白,怎么实现JavaScript层与原生层的通信。这里可以直接查看官方的文档,有这详细的说明【原生模块通信】。如果你是新手请仔细看文档一步一步来。 简单来说:就是我们需要一个自定义的package,一个自定义的module。将module添加到package中,再将package添加到MainApplication.java中。我们在module中定义一个利用@ReactMehod注解的方法,以提供JavaScript进行调用(注意引入对应的module,module的名称要写对),从而达到JavaScript调用Android方法的目的。
第二步:这里时候相信你己经可以通过JavaScript去调用你在Activity中写的Java/kotiln代码了。接下来就是利用Intent去跳转到另外一个新建的Activity上。这个方案可以在android的官方文档上找到。【启动另外一个activiy】
Android代码如下:(注意对应包的引入)
import android.app.Activity;
import android.content.Intent;
import android.widget.Toast;
..................
/// 你的某个自定义的module类中
@ReactMethod
public void test(String name, String params) {
try {
Activity currentActivity = getCurrentActivity();
if (null != currentActivity) {
Class toActivity = Class.forName(name);
if (null != toActivity) {
Intent intent = new Intent(currentActivity, toActivity);
intent.putExtra("params", params);
currentActivity.startActivity(intent);
} else {
Toast.makeText(getReactApplicationContext(), "toActivity [" + name + "] is null", Toast.LENGTH_LONG)
.show();
}
}
} catch (Exception e) {
throw new JSApplicationIllegalArgumentException(
"不能打开Activity : " + e.getMessage());
}
}
JavaScript代码如下:
这里的目标Activiy名称要与你本地项目的Activiy名称对应。rn_sample是我的ReactNative项目名称,JavaSecondActivity是我自定义的一个Activiy。
第三步
创建一个自定义的Activity。如上图我创建的JavaSecondActivity。再在AndroidManifest.xml中注册该Activity。注意你的文件路径。填写位置应该与默认的activity平级,在
至此,菜都上齐了。
只需要你再重新编译跑一遍就行了。至此你点击这个button是它会帮你调用module中的方法,该原生方法又帮你跳转到你新的空白的Activity上了。搞定。
还有就是原生的Activiy是通过直接触发调用finish(),进行页面销毁的。表现形式就和页面后退一致。这与JavaScript中调用路由有所不同。
另外再补充一点:如果你和我一样需要面对Java与Kotlin混编的情况,记住添加插件否则AndroidStudio编译不通过。
代码如下:
在打包时,也注意一下是否要开启混淆。有些库混淆后导致无法找到对应的变量或方法导致运行崩溃。还找不到报错的具体行列。我就被坑了。
总结:个人感觉虽然ReactNative帮助我们前端程序员进入到了移动端开发的领域,但还是需要一定的原生端的知识储备,不然在遇到问题时,也不知道问题的根本在哪里。