This documentation is available as Markdown for AI agents and LLMs. See the full Markdown index or append .md to any documentation URL.
包装第三方原生库
编辑页面
了解如何使用 Expo Modules API 围绕两个独立的原生库创建一个简单的包装器。
Expo 模块使得在 React Native 项目中轻松使用为 Android 和 iOS 构建的原生外部库成为可能。本教程重点介绍如何利用 Expo Modules API,使用两个可在两个原生平台上访问的相似库创建径向图表。
iOS 库受到 Android 库的启发,因此它们都具有相似的 API 和功能。这使它们成为本教程的一个很好的示例。

在这个视频中,你将学习如何使用 Expo Modules API 包装原生库。
1
创建一个新模块
以下步骤假设新模块是在一个新的 Expo 项目中创建的。不过,你也可以按照替代说明在现有项目中创建新模块。
或者,你可以将新模块作为现有 Expo 项目目录中的一个视图来使用。在项目目录中运行以下命令:
- npx create-expo-module --local expo-radial-chart现在,打开新创建的 modules/expo-radial-chart 目录,开始编辑原生代码。
通过运行以下命令,创建一个可以发布到 npm 并在任何 Expo 应用中使用的空 Expo 模块:
- npx create-expo-module expo-radial-chart提示:如果你不打算发布这个库,请在终端窗口中的所有提示处按下 Return 以接受默认值。
现在,打开新创建的 expo-radial-chart 目录,开始编辑原生代码。
2
运行示例项目
为了验证一切是否正常运行,让我们运行示例项目。
如果你是从现有 Expo 项目开始的,请在 Expo 项目的根目录中运行以下命令:
# 在 Android 上运行 example-expo-app- npx expo run:android# 在 iOS 上运行示例应用- npx expo run:ios如果你是从一个新的模块项目开始的,请打开一个终端窗口,启动 TypeScript 编译器以监视更改,并重新构建模块 JavaScript:
# 确保在运行下面的命令之前你已位于 expo-radial-chart 目录中- npm run build在另一个终端窗口中,编译并运行示例应用:
- cd example-expo-app# 在 Android 上运行 example-expo-app- npx expo run:android# 在 iOS 上运行示例应用- npx expo run:ios3
添加原生依赖
通过编辑 expo-radial-chart/android/build.gradle 和 expo-radial-chart/ios/ExpoRadialChart.podspec 文件,将原生依赖添加到模块中:
你是否想使用 .aar 依赖?
在 android 目录中,再创建一个名为 libs 的目录,并将 .aar 文件放入其中。然后,通过 autolinking 将该文件作为 Gradle 项目添加:
最后,将依赖添加到 android/build.gradle 文件中的 dependencies 列表里,并使用依赖指定的名称,前面加上 ${project.name}$ 前缀:
在 android 目录中,再创建一个名为 libs 的目录,并将 .aar 文件放入其中。然后,将该目录添加为仓库:
最后,将依赖添加到 dependencies 列表中。不要使用文件名,而是使用包路径,并在末尾加上 @aar:
你是否想使用 .xcframework 或 .framework 依赖?
在 iOS 上,你也可以通过使用 vendored_frameworks 配置选项来使用以 framework 形式打包的依赖。
注意:用于指定 framework 路径的文件模式是相对于 podspec 文件的, 并且不支持遍历父目录(..),这意味着你需要将 framework 放在 ios 目录 中(或 ios 的子目录中)。
添加 framework 后,请确保 source_files 选项的文件模式不会匹配 framework 中的任何文件。实现这一点的一种方法是将 iOS 源 Swift 文件(即 ExpoRadialChartView.swift 和 ExpoRadialChartModule.swift)移动到一个与放置 framework 的位置分开的 src 目录中,并将 source_files 选项更新为只匹配 src 目录:
你的 ios 目录最终应具有类似以下的文件结构:
FrameworksMyFramework.frameworksrcExpoRadialChartView.swiftExpoRadialChartModule.swiftExpoRadialChart.podspec4
定义一个 API
要在应用中使用该模块,请定义这些 props 的类型。它接受一个系列列表——每个系列都包含一个颜色和一个百分比值。
import { ViewStyle } from 'react-native/types'; export type ChangeEventPayload = { value: string; }; type Series = { color: string; percentage: number; }; export type ExpoRadialChartViewProps = { style?: ViewStyle; data: Series[]; };
由于本示例中该模块没有为 web 实现,我们将替换 src/ExpoRadialChartView.web.tsx 文件:
import * as React from 'react'; export default function ExpoRadialChartView() { return <div>未实现</div>; }
5
在 Android 上实现模块
现在你可以通过编辑占位文件并进行以下更改来实现原生功能:
- 创建一个
PieChart实例,并将其layoutParams设置为与父视图一致。然后,使用addView函数将其添加到视图层级中。 - 定义一个接受
Series对象列表的setChartData函数。你可以遍历该列表,为每个系列创建一个PieEntry,并将颜色存储在一个单独的列表中。 - 创建一个
PieDataSet,使用它创建一个PieData对象,并将其设置为PieChart实例的数据。
package expo.modules.radialchart import android.content.Context import android.graphics.Color import androidx.annotation.ColorInt import com.github.mikephil.charting.charts.PieChart import com.github.mikephil.charting.data.PieData import com.github.mikephil.charting.data.PieDataSet import com.github.mikephil.charting.data.PieEntry import expo.modules.kotlin.AppContext import expo.modules.kotlin.records.Field import expo.modules.kotlin.records.Record import expo.modules.kotlin.views.ExpoView class Series : Record { @Field val color: String = "#ff0000" @Field val percentage: Float = 0.0f } class ExpoRadialChartView(context: Context, appContext: AppContext) : ExpoView(context, appContext) { internal val chartView = PieChart(context).also { it.layoutParams = LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT) addView(it) } fun setChartData(data: ArrayList<Series>) { val entries: ArrayList<PieEntry> = ArrayList() val colors: ArrayList<Int> = ArrayList() for (series in data) { entries.add(PieEntry(series.percentage)) colors.add(Color.parseColor(series.color)) } val dataSet = PieDataSet(entries, "DataSet"); dataSet.colors = colors; val pieData = PieData(dataSet); chartView.data = pieData; chartView.invalidate(); } }
你还需要使用 Prop 函数来定义 data prop,并在 prop 变化时调用原生的 setChartData 函数:
package expo.modules.radialchart import expo.modules.kotlin.modules.Module import expo.modules.kotlin.modules.ModuleDefinition class ExpoRadialChartModule : Module() { override fun definition() = ModuleDefinition { Name("ExpoRadialChart") View(ExpoRadialChartView::class) { Prop("data") { view: ExpoRadialChartView, prop: ArrayList<Series> -> view.setChartData(prop); } } } }
6
在 iOS 上实现模块
现在你可以通过编辑占位文件并进行以下更改来实现原生功能:
- 创建一个新的
PieChartView实例,并使用addSubview函数将其添加到视图层级中。 - 设置
clipsToBounds属性,并重写layoutSubviews函数,以确保图表视图始终与父视图大小相同。 - 创建一个接受系列列表的
setChartData函数,使用数据创建一个PieChartDataSet实例,并将其赋值给PieChartView实例的data属性。
import ExpoModulesCore import DGCharts struct Series: Record { @Field var color: UIColor = UIColor.black @Field var percentage: Double = 0 } class ExpoRadialChartView: ExpoView { let chartView = PieChartView() required init(appContext: AppContext? = nil) { super.init(appContext: appContext) clipsToBounds = true addSubview(chartView) } override func layoutSubviews() { chartView.frame = bounds } func setChartData(data: [Series]) { let set1 = PieChartDataSet(entries: data.map({ (series: Series) -> PieChartDataEntry in return PieChartDataEntry(value: series.percentage) })) set1.colors = data.map({ (series: Series) -> UIColor in return series.color }) let chartData: PieChartData = [set1] chartView.data = chartData } }
你还需要使用 Prop 函数来定义 data prop,并在 prop 变化时调用原生的 setChartData 函数:
import ExpoModulesCore public class ExpoRadialChartModule: Module { public func definition() -> ModuleDefinition { Name("ExpoRadialChart") View(ExpoRadialChartView.self) { Prop("data") { (view: ExpoRadialChartView, prop: [Series]) in view.setChartData(data: prop) } } } }
7
编写一个使用该模块的示例应用
你可以更新 src/app 目录中的应用来测试该模块。使用 ExpoRadialChartView 组件渲染一个包含三个扇区的饼图:
import { ExpoRadialChartView } from '@/modules/expo-radial-chart'; import { StyleSheet } from 'react-native'; export default function App() { return ( <ExpoRadialChartView style={styles.container} data={[ { color: '#ff0000', percentage: 0.5, }, { color: '#00ff00', percentage: 0.2, }, { color: '#0000ff', percentage: 0.3, }, ]} /> ); } const styles = StyleSheet.create({ container: { flex: 1, }, });
提示:如果你创建的是新模块,请确保将导入语句更新为:import { ExpoRadialChartView } from 'expo-radial-chart';
恭喜!你已经使用 Expo Modules API 创建了第一个围绕两个独立第三方原生库的简单封装。
下一步
使用 Kotlin 和 Swift 创建原生模块的参考。