写点什么

mand-mobile-rn 多 Android Module link 实现

  • 2019-09-19
  • 本文字数:3958 字

    阅读完需:约 13 分钟

mand-mobile-rn 多 Android Module link 实现

在 react-native 生态中,包含原生 android 代码的 library 项目,都是通过项目的根文件夹中的 android 文件夹或者 android 文件夹下的 app 文件夹作为 library module 提供外部依赖。mand-mobile-rn 通过 rnpm 接口实现了对 react-native library 项目多个 Android module 的 link 实现。


mand-mobile-rn 是滴滴金融 FE 团队开发的面向金融场景的 react-native 组件库。


使用 react-native 的小伙伴,一定对下面列出的 react-native library 项目比较熟悉,这些组件都是通过封装原生模块或源生 UI 组件提供 react-native 侧调用。


  • react-native-vector-icons

  • react-native-svg

  • react-native-linear-gradient


上述列出的项目在 package.json 依赖 yarn 之后,调用 react-native link 命令,会在 Android 侧依赖引入相应的 library module,提供 react-native 依赖 Android 源生模块或者组件。


rootProject.name = 'samples'include ':react-native-vector-icons'project(':react-native-vector-icons').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-vector-icons/android')include ':react-native-svg'project(':react-native-svg').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-svg/android')include ':react-native-linear-gradient'project(':react-native-linear-gradient').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-linear-gradient/android')include ':app'
复制代码


通过 link 这三个项目,可以看出都是添加 android 目录的相对路径到 settings.gradle 提供外部依赖。


在 react-native 生态中,包含原生 android 代码的 library 项目,都是通过项目的根文件夹中的 android 文件夹或者 android 文件夹下的 app 文件夹作为 library module 提供外部依赖。


在 mand-mobile-rn 中,分别对 ImagePicker,RefreshControl,NumberKerboard 三个原生模块创建了三个原生 android module 提供外部依赖,有别于传统的 react-native library 项目,这三个 module 文件夹并没有放在 android 文件夹下(即使放在 android 文件夹下,也无法同时 link 这个三个 module)。


.├── android├── build├── docs├── gradle├── ios├── samples├── scripts├── sites├── src│   ├── _styles│   ├── _utils│   ├── assets│   ├── components│   └── natives│       ├── Core│       ├── ImagePicker│       │   ├── android│       │   └── ios│       ├── NumberKeyboard│       │   ├── android│       │   └── ios│       └── RefreshControl│           ├── android│           └── ios├── template└── tests
复制代码


mand-mobile-rn 是如何提供使用方集成的?通过下面的文章,来一步一步介绍。

1.react-native link 命令是如何实现的?

在上文中写到 “即使放在 android 文件夹下,也无法同时 link 这个三个 module” ,真的是这样吗?下面通过 react-native-cli 项目的源码来证实。


在 packages/cli/src/core/android/findAndroidAppFolder.js 文件中,定义了如下代码,用来寻找 link 的 library 项目中的 android 目录。


export default function findAndroidAppFolder(folder) {  const flat = 'android';  const nested = path.join('android', 'app');
if (fs.existsSync(path.join(folder, nested))) { return nested; }
if (fs.existsSync(path.join(folder, flat))) { return flat; }
return null;}
复制代码


这段代码可以看出,首先判断 android/app 文件夹是否存在,如果不存在,继续判断 android 文件夹是否存在。通过代码也就说明了,react-native link 命令,只会调用 library 项目根下的 android/app 或者 android 文件夹作为 library module,提供外部依赖。

2.react-native-code-push 引发的思考

在集成 react-native-code-push 时,code push 会让你输入


”deployment key“,这和其他的 react-native library 项目的行为并不一致。在阅读 react-native-code-push 源码时, 发现 package.json 中有如下声明。


"rnpm": {    "android": {      "packageInstance": "new CodePush(${androidDeploymentKey}, getApplicationContext(), BuildConfig.DEBUG)"    },    "ios": {      "sharedLibraries": [        "libz"      ]    },    "params": [      {        "type": "input",        "name": "androidDeploymentKey",        "message": "What is your CodePush deployment key for Android (hit <ENTER> to ignore)"      }    ],    "commands": {      "postlink": "node node_modules/react-native-code-push/scripts/postlink/run"    }  }
复制代码


这段声明,看起来就是让输入”deployment key“的原因。


通过 Google,可以搜索到 rnpm 项目(https://github.com/rnpm/rnpm ),在 react-native v0.27 版本时,合并进入 react-native-cli,但是 react-native-cli 文档中并没有详细介绍 rnpm,具体介绍和使用还要看 https:// github. com/rnpm/rnpm 。


通过阅读文档,可知 commands prelink/postlink 可以指定脚本,用来 hook react-native link 命令执行前和执行后。


react-native-code-push 利用 postlink 来执行 node 脚本进行依赖代码的写入。


react-native-code-push 脚本代码:


https:// github. com/Microsoft/react-native-code-push/blob/master/scripts/postlink/android/postlink.js

3.mand-mobile-rn 实现

为了实现一次调用 link 命令,集成三个 android module,mand-mobile-rn 使用和 react-native-code-push 同样的原理,通过在 commands postlink 指定脚本,写入代码实现依赖。


注册一个 library 原生模块或原生组件到 react-native Android 工程中,大概需要如下三个步骤:


注册组件 module 到 ./android/settings.gradle


在 ./android/app/build.gradle 中声明依赖 module


在 ReactNativeHost.getPackages() 中注册组件的 package

applyPatch.js

上述的三个步骤,都要写入代码到文件中,因此定义一个 applyPatch.js 文件作为写入代码工具方法,代码如下:


var fs = require('fs')
function applyPatch(patch) { if (!fs.existsSync(patch.path)) { return Promise.reject(patch.noExistNotice) } var content = fs.readFileSync(patch.path, 'utf-8')
console.log(`Writing ${patch.path}`)
if (~content.indexOf(patch.patch)) { console.log(patch.alreadyAddedNotice) } else { fs.writeFileSync( patch.path, content.replace(patch.pattern, (match) => `${match}${patch.patch}`), ) } return Promise.resolve()}
module.exports = applyPatch
复制代码


读取目标文件内容,然后替换匹配的内容,最终再次写回到文件当中。

natives.json

因为每个模块的命名和路径肯定是不同的,同时为了方便 js 读取,定义 natives.json 文件来声明每个原生模块的全路径名和 module 位置。代码如下:


[  {    "moduleName": "mand-mobile-image-picker",    "packageName": "com.mandmobile.react.imagepicker.MDImagePickerPackage",    "modulePath": "src/natives/ImagePicker/android"  },  {    "moduleName": "mand-mobile-number-keyboard",    "packageName": "com.mandmobile.MDNumberKeyboardPackage",    "modulePath": "src/natives/NumberKeyboard/android"  },  {    "moduleName": "mand-mobile-refresh-control",    "packageName": "com.mandmobile.react.refreshcontrol.MDRefreshControlPackage",    "modulePath": "src/natives/RefreshControl/android"  }]
复制代码

android/postlink.js

通过读取 natives.json 获取需要写入的组件,然后通过 Promise 顺序分别写入 settings.gralde,app/build.gradle,MainApplication。


module.exports = () => {  console.log('Running android postlink script')  if (!nativeModules || nativeModules.lenght == 0) {    return Promise.reject()  }
return applyPatch(rootBuildGradlePatch()) .then(() => applyPatch(settingGradlePatch(nativeModules))) .then(() => applyPatch(appBuildGradlePatch(nativeModules))) .then(() => applyPatch(importApplicationPatch(nativeModules))) .then(() => applyPatch(packagePatch(nativeModules)))}
复制代码

settingGradlePatch.js

settingGradlePatch.js 负责组织写入数据,以符合 applyPatch.js 执行写入。代码如下:


function settingGradlePatch(mandMobilPath,natives) {  var patch = ''
for (native of natives) { patch += `include ':${native.moduleName}'project(':${native.moduleName}').projectDir = new File(rootProject.projectDir, '../${mandMobilPath}/${native.modulePath}')` }
return { path: path.join('android', 'settings.gradle'), pattern: /include\s* \'\:app\'/, patch, noExistNotice: `Couldn't find "settings.gradle" file. Please see Doc`, alreadyAddedNotice: `"settings.gradle" is already linked`, }}
复制代码


appBuildGradlePatch,importApplicationPatch 等原理大同小异,都是通过正则匹配之后写入代码,不再重复。这里是源码入口

4.总结

rnpm 极大方便了 react-native library 开发方,把复杂的依赖方式,写成脚本注入到代码中。通过 rnpm ,未来 mand-mobile-rn 可以扩展在 link 命令集成时,在命令行中选择是否依赖源生模块,以及依赖那个原生模块。


本文转载自公众号滴滴技术(ID:didi_tech)。


原文链接:


https://mp.weixin.qq.com/s/Cn0MRzZi7VPNDm_kGtRkwA


2019-09-19 17:032758

评论 1 条评论

发布
用户头像
竟然看到自己多年前的文章。
2022-09-02 20:05 · 北京
回复
没有更多了
发现更多内容

充电桩测试系统(源码+文档+讲解+演示)

深圳亥时科技

2025大型企业财务数智化峰会·上海站圆满落幕!

用友BIP

数智化 用友BIP AI+财务

启动!南宁城投集团携手用友共建全球领先智能化财务共享平台

用友BIP

AI 企业数智化 用友BIP 财务共享

深入理解 Bitmap 索引:原理、场景与应用案例

镜舟科技

数据分析 OLAP 分析型数据库 StarRocks Bitmap 索引

企业AI 智启新底座,共探AI与数智化底座的融合创新路径

用友BIP

数智化 用友BIP 企业AI

CST软件如何理解远场的坐标、分量和极化

思茂信息

cst电磁仿真 CST软件 CST Studio Suite

物资管理系统(源码+文档+讲解+演示)

深圳亥时科技

人工智能产品测试 | 特征的概念:离散与连续

测试人

人工智能

签约+战略合作!水电五局与用友擘画工程项目管理数智新蓝图

用友BIP

数智化 用友BIP 企业AI 企业管理工程

AI口语练习APP的接口优化

北京木奇移动技术有限公司

软件外包公司 AI口语练习 AI英语学习

AI赋能时尚零售功能篇:全渠道全流程商品管理数字化

第七在线

淘宝天猫宝贝详情优惠券数据采集接口:深入探究与实践

tbapi

淘宝API 淘宝优惠券接口 淘宝商品优惠券接口 天猫优惠券接口

无刷电机工厂生产管理MES系统解决方案

万界星空科技

无刷电机 mes 制造业工厂 电机行业 电机MES

AI 真的懂你问的问题吗?

沉浸式趣谈

云报工系统(源码+文档+讲解+演示)

深圳亥时科技

淘宝天猫宝贝详情页面商品评论采集接口全解析

tbapi

淘宝商品评论接口 淘宝API 淘宝评论接口

【IoTDB 线上小课 13】包教包会的 IoTDB 安装教程来啦!

Apache IoTDB

DeepSeek将如何改变我们的日常生活和工作?

天津汇柏科技有限公司

AI 人工智能 DeepSeek

BOE(京东方)携前沿显示技术亮相ICDT 2025 “绿色+科技”引领产业持续向新

爱极客侠

轻帆云荣获“智慧商业数字化运营优秀服务商”奖项,AITSM赋能零售新未来

云智慧AIOps社区

ITSM ITSM软件 工单管理 工单系统 工单处理

人工智能丨测试人必看!MCP协议如何让测试工具“智商”翻倍?

测试人

人工智能

蚂蚁集团在加速互联网和金融服务创新上的实践——平台工程解决方案

蚂蚁开源

蚂蚁集团 kusionstack 蚂蚁开源

AI技术赋能企业财务管理,用友BIP创新五大智能财务场景

用友BIP

AI 数智化 企业财务 用友BIP 财务智能体

2025企业数智化平台创新峰会成功召开!

用友BIP

AI+ 数智化 企业创新 用友BIP 企业AI

人工智能丨2025年,测试从业者应如何拥抱智能体(AI Agent)?

测试人

AI Agent赛道:昙花一现还是生态革命?6大咖拆解泡沫与未来

TechubNews

AI Agents 币圈不设防

超 400 人团队律所,如何用 NocoBase 高效管理律师提成?

NocoBase

开源 零代码 客户案例 薪酬绩效管理 律师事务所

用友与中国化学数科公司达成战略合作,助推化工行业数智化发展!

用友BIP

智能体 数智化 用友BIP 化工行业

智能制造:关于专精特新的解读

积木链小链

数字化 智能制造

AI口语练习APP的性能测试

北京木奇移动技术有限公司

软件外包公司 AI口语练习 AI英语学习

烟草业需要用到堡垒机的几个情形简单说明

行云管家

网络安全 数据安全 堡垒机

mand-mobile-rn 多 Android Module link 实现_文化 & 方法_游子聪_InfoQ精选文章