React Native 接入 eCharts

React Native 图表接入指南

概述

本文档详细介绍了在React Native项目中接入ECharts图表的完整步骤,包括依赖安装、组件配置、数据获取、图表渲染等各个环节。

目录

  • 1. 环境准备
  • 2. 依赖安装
  • 3. 图表组件创建
  • 4. 数据获取Hook
  • 5. 图表配置
  • 6. 组件集成
  • 7. 国际化支持
  • 8. 最佳实践
  • 9. 常见问题

1. 环境准备

1.1 项目要求

  • React Native 0.76.9+
  • Expo SDK 52+
  • TypeScript 5.3.3+
  • Node.js 18.18.0+

1.2 开发环境

确保已安装以下工具:

  • Node.js 和 npm/yarn
  • React Native CLI 或 Expo CLI
  • iOS Simulator (macOS) 或 Android Emulator

2. 依赖安装

2.1 核心依赖

# 安装图表核心库
npm install echarts@^5.6.0# 安装React Native图表渲染器
npm install @wuba/react-native-echarts@^2.0.3# 安装SVG支持(图表渲染需要)
npm install react-native-svg@^15.8.0# 安装日期处理库(用于图表时间轴格式化)
npm install date-fns@^4.1.0

这个过程是这样的:

  1. ECharts 核心库 ( echarts ) :负责所有的数据处理、图表逻辑计算和配置项解析。它会生成一个虚拟的、与平台无关的渲染指令。
  2. SVG 渲染器 ( SVGRenderer ) :这个渲染器来自于 @wuba/react-native-echarts 包,它的作用是接收 ECharts 核心库生成的渲染指令,并将其转换成 SVG 元素。
  3. React Native SVG ( react-native-svg ) :这个库提供了在 React Native 中渲染 SVG 的能力。它会将 SVGRenderer 生成的 SVG 元素真正在原生视图上绘制出来。
    所以,整个流程可以看作是 ECharts (逻辑) -> SVGRenderer (转换为 SVG) -> react-native-svg (在屏幕上绘制) 。这种方式使得强大的 ECharts 库能够跨平台运行在没有原生 Canvas 和 DOM 环境的 React Native 中

2.2 可选依赖

# 如果需要健康数据(如心率图表示例)
npm install react-native-health@^1.19.0# 如果需要更多图表类型
npm install @types/echarts

2.3 依赖说明

依赖包版本作用
echarts^5.6.0图表核心库,提供丰富的图表类型
@wuba/react-native-echarts^2.0.3React Native适配的ECharts渲染器
react-native-svg^15.8.0SVG渲染支持,图表显示必需
date-fns^4.1.0日期处理工具,用于时间轴格式化

3. 图表组件创建

3.1 基础组件结构

创建文件:app/components/HeartRateChart.tsx

import { useRef, useEffect, useMemo } from "react"
import { StyleProp, View, ViewStyle } from "react-native"
import { echarts } from "../utils/echarts" // 导入集中的 echarts 实例
import SvgChart from "@wuba/react-native-echarts/svgChart"
import { useHealthData } from "../hooks/useHealthData"
import { HealthValue } from "react-native-health"
import { format } from "date-fns"
import { ECharts } from "echarts/core"// 不再需要在此处注册组件,已在 app/utils/echarts.ts 中集中处理interface HeartRateChartProps {style?: StyleProp<ViewStyle>
}const CHART_HEIGHT = 300
const CHART_WIDTH = 350export function HeartRateChart(props: HeartRateChartProps) {const { style } = propsconst chartRef = useRef<any>(null)const { heartRateSamples, fetchHeartRateSamples, permissionsGranted } = useHealthData({requestPermissions: true,autoFetch: false,})// 数据获取useEffect(() => {if (permissionsGranted) {const endDate = new Date()const startDate = new Date()startDate.setDate(endDate.getDate() - 1)fetchHeartRateSamples(startDate, endDate)}}, [permissionsGranted, fetchHeartRateSamples])// 图表配置const chartOption = useMemo(() => {if (!heartRateSamples || heartRateSamples.length === 0) {return {}}const data = heartRateSamples.map((sample: HealthValue) => [new Date(sample.startDate),sample.value,])return {tooltip: {trigger: "axis",formatter: (params: any) => {const param = params[0]const date = new Date(param.axisValue)const value = param.data[1]return `${format(date, "MM-dd HH:mm")}<br/>心率: ${value}`},},xAxis: {type: "time",axisLabel: {formatter: (value: number) => {return format(new Date(value), "HH:mm")},},},yAxis: {type: "value",name: "心率 (bpm)",min: (value: { min: number }) => Math.floor(value.min / 10) * 10,},series: [{data,type: "line",smooth: true,showSymbol: false,lineStyle: {width: 2,},},],grid: {left: "12%",right: "5%",bottom: "10%",top: "10%",},}}, [heartRateSamples])// 图表初始化和更新useEffect(() => {let chartInstance: ECharts | undefinedif (chartRef.current && Object.keys(chartOption).length > 0) {chartInstance = echarts.init(chartRef.current, "light", {renderer: "svg",width: CHART_WIDTH,height: CHART_HEIGHT,})chartInstance.setOption(chartOption)}return () => {chartInstance?.dispose()}}, [chartOption])return (<View style={style}><SvgChart ref={chartRef} /></View>)
}

3.2 组件导出

app/components/index.ts 中添加导出:

export * from "./HeartRateChart"

4. 数据获取Hook

4.1 创建数据Hook

创建文件:app/hooks/useHealthData.ts

import { useState, useCallback, useEffect } from "react"
import AppleHealthKit, { HealthKitPermissions, HealthValue } from "react-native-health"interface HealthDataState {stepCount: number | nullheartRateSamples: HealthValue[]isLoading: booleanerror: string | nullpermissionsGranted: boolean
}interface UseHealthDataOptions {requestPermissions?: booleanautoFetch?: boolean
}export const useHealthData = (options: UseHealthDataOptions = {}) => {const { requestPermissions = true, autoFetch = true } = optionsconst [healthData, setHealthData] = useState<HealthDataState>({stepCount: null,heartRateSamples: [],isLoading: false,error: null,permissionsGranted: false,})// 初始化 HealthKit 并请求权限const initializeHealthKit = useCallback(async () => {if (!requestPermissions) returnsetHealthData((prev) => ({ ...prev, isLoading: true, error: null }))const permissions = {permissions: {read: [AppleHealthKit.Constants.Permissions.Steps,AppleHealthKit.Constants.Permissions.HeartRate,AppleHealthKit.Constants.Permissions.StepCount,],write: [],},} as HealthKitPermissionsreturn new Promise<void>((resolve, reject) => {AppleHealthKit.initHealthKit(permissions, (error: string) => {if (error) {const errorMessage = `无法授予 HealthKit 权限: ${error}`console.error("HealthKit 权限请求失败:", errorMessage)setHealthData((prev) => ({...prev,isLoading: false,error: errorMessage,permissionsGranted: false,}))reject(new Error(errorMessage))return}setHealthData((prev) => ({...prev,isLoading: false,permissionsGranted: true,}))resolve()})})}, [requestPermissions])// 获取心率样本const fetchHeartRateSamples = useCallback(async (startDate?: Date, endDate?: Date) => {if (!healthData.permissionsGranted) {const errorMsg = "HealthKit 权限未授予,无法获取心率数据"console.error(errorMsg)throw new Error(errorMsg)}setHealthData((prev) => ({ ...prev, isLoading: true, error: null }))const heartRateOptions = {startDate: (startDate || new Date(new Date().getTime() - 24 * 60 * 60 * 1000)).toISOString(),endDate: (endDate || new Date()).toISOString(),}return new Promise<HealthValue[]>((resolve, reject) => {AppleHealthKit.getHeartRateSamples(heartRateOptions,(err: string, results: HealthValue[]) => {if (err) {const errorMessage = `获取心率样本时出错: ${err}`console.error(errorMessage)setHealthData((prev) => ({...prev,isLoading: false,error: errorMessage,}))reject(new Error(errorMessage))return}setHealthData((prev) => ({...prev,heartRateSamples: results,isLoading: false,}))resolve(results)},)})},[healthData.permissionsGranted],)// 获取所有健康数据const fetchAllHealthData = useCallback(async () => {if (!healthData.permissionsGranted) {return}try {await fetchHeartRateSamples()} catch (error) {console.error("获取健康数据时出错:", error)}}, [fetchHeartRateSamples, healthData.permissionsGranted])// 清除错误const clearError = useCallback(() => {setHealthData((prev) => ({ ...prev, error: null }))}, [])// 初始化useEffect(() => {if (requestPermissions) {initializeHealthKit().then(() => {setTimeout(() => {if (autoFetch) {fetchAllHealthData()}}, 100)}).catch((error) => {console.error("初始化 HealthKit 失败:", error)})}}, [requestPermissions, autoFetch, initializeHealthKit, fetchAllHealthData])return {// 状态...healthData,// 方法initializeHealthKit,fetchHeartRateSamples,fetchAllHealthData,clearError,}
}

4.2 Hook导出

app/hooks/index.ts 中添加导出:

export * from "./useHealthData"

5. 图表配置

5.1 基础配置

const baseChartOption = {// 提示框配置tooltip: {trigger: "axis",backgroundColor: "rgba(0, 0, 0, 0.8)",borderColor: "rgba(255, 255, 255, 0.2)",textStyle: {color: "#fff",},},// 网格配置grid: {left: "12%",right: "5%",bottom: "10%",top: "10%",containLabel: true,},// 动画配置animation: true,animationDuration: 1000,animationEasing: "cubicOut",
}

5.2 时间轴配置

const timeAxisConfig = {xAxis: {type: "time",axisLabel: {formatter: (value: number) => format(new Date(value), "HH:mm"),color: "#666",fontSize: 12,},axisLine: {lineStyle: {color: "#ddd",},},splitLine: {show: true,lineStyle: {color: "#f0f0f0",type: "dashed",},},},
}

5.3 数值轴配置

const valueAxisConfig = {yAxis: {type: "value",name: "心率 (bpm)",nameTextStyle: {color: "#666",fontSize: 12,},axisLabel: {color: "#666",fontSize: 12,},axisLine: {lineStyle: {color: "#ddd",},},splitLine: {show: true,lineStyle: {color: "#f0f0f0",type: "dashed",},},min: (value: { min: number }) => Math.floor(value.min / 10) * 10,},
}

5.4 数据系列配置

const seriesConfig = {series: [{data: chartData,type: "line",smooth: true,showSymbol: false,lineStyle: {width: 2,color: "#ff6b6b",},areaStyle: {color: {type: "linear",x: 0,y: 0,x2: 0,y2: 1,colorStops: [{ offset: 0, color: "rgba(255, 107, 107, 0.3)" },{ offset: 1, color: "rgba(255, 107, 107, 0.1)" },],},},},],
}

6. 组件集成

6.1 创建演示组件

创建文件:app/screens/DemoShowroomScreen/demos/DemoHeartRateChart.tsx

import { HeartRateChart } from "../../../components"
import { View, StyleSheet } from "react-native"
import { Text } from "../../../components"export const DemoHeartRateChart = () => {return (<View style={styles.container}><Text preset="heading" style={styles.title}>24小时心率图表</Text><HeartRateChart /></View>)
}const styles = StyleSheet.create({container: {alignItems: "center",padding: 20,},title: {marginBottom: 20,textAlign: "center",},
})

6.2 添加到演示页面

app/screens/DemoShowroomScreen/DemoShowroomScreen.tsx 中:

import { FC } from "react"
import { Screen } from "../../components"
import { DemoHeartRateChart } from "./demos"export const DemoShowroomScreen: FC = function DemoShowroomScreen() {return (<Screen preset="fixed" safeAreaEdges={["top"]}><DemoHeartRateChart /></Screen>)
}

6.3 导出演示组件

app/screens/DemoShowroomScreen/demos/index.ts 中:

export * from "./DemoHeartRateChart"

7. 国际化支持

7.1 中文翻译

app/i18n/zh.ts 中添加:

const zh = {// ... 其他翻译demoShowroomScreen: {// ... 其他翻译demoHeartRateChart: "心率图表",demoHeartRateChartDesc: "一个显示心率随时间变化的图表。",},
}

7.2 英文翻译

app/i18n/en.ts 中添加:

const en = {// ... 其他翻译demoShowroomScreen: {// ... 其他翻译demoHeartRateChart: "Heart Rate Chart",demoHeartRateChartDesc: "A chart showing heart rate over time.",},
}

8. 最佳实践

8.1 性能优化

  1. 使用useMemo缓存图表配置
const chartOption = useMemo(() => {// 图表配置逻辑
}, [data, theme])
  1. 合理管理图表实例
useEffect(() => {let chartInstance: ECharts | undefinedif (chartRef.current && data.length > 0) {chartInstance = echarts.init(chartRef.current, "light", {renderer: "svg",width: CHART_WIDTH,height: CHART_HEIGHT,})chartInstance.setOption(chartOption)}return () => {chartInstance?.dispose()}
}, [chartOption])
  1. 避免不必要的重新渲染
const MemoizedChart = React.memo(HeartRateChart)

8.2 错误处理

  1. 数据验证
const chartOption = useMemo(() => {if (!data || data.length === 0) {return {}}// 图表配置
}, [data])
  1. 权限检查
useEffect(() => {if (permissionsGranted) {fetchData()}
}, [permissionsGranted])
  1. 加载状态
{isLoading && <LoadingSpinner />}
{error && <ErrorMessage error={error} onRetry={fetchData} />}

8.3 响应式设计

  1. 动态尺寸
const [chartSize, setChartSize] = useState({ width: 350, height: 300 })useEffect(() => {const updateSize = () => {const { width } = Dimensions.get('window')setChartSize({width: width - 40, // 减去paddingheight: 300,})}updateSize()Dimensions.addEventListener('change', updateSize)return () => {Dimensions.removeEventListener('change', updateSize)}
}, [])
  1. 主题适配
const chartOption = useMemo(() => ({// ... 其他配置backgroundColor: theme.colors.background,textStyle: {color: theme.colors.text,},
}), [theme, data])

8.4 统一ECharts实例管理

为了避免在多个组件中重复初始化ECharts模块导致 [ReferenceError: Property 'document' doesn't exist] 等问题,建议创建一个中心化的echarts.ts文件来统一管理ECharts实例和模块注册。

创建 app/utils/echarts.ts:

import * as echarts from "echarts/core"
import { SVGRenderer } from "@wuba/react-native-echarts/svgChart"
import {LineChart,BarChart,GaugeChart,CustomChart,
} from "echarts/charts"
import {GridComponent,TooltipComponent,LegendComponent,
} from "echarts/components"// 注册所有需要的组件
echarts.use([SVGRenderer,LineChart,BarChart,GaugeChart,CustomChart,GridComponent,TooltipComponent,LegendComponent,
])export { echarts }

在组件中使用:

import { echarts } from "../utils/echarts" // 导入集中的 echarts 实例
// ...
// 不再需要 echarts.use(...)

9. 常见问题

9.1 图表不显示

问题:图表组件渲染但图表内容不显示

解决方案

  1. 检查模块注册:确保所有需要的图表类型(如 LineChart)和组件(如 TooltipComponent)都已在 app/utils/echarts.ts 中导入并使用 echarts.use() 注册。这是最常见的原因,尤其是在添加新图表类型后。
  2. 确认容器尺寸:确保 <SvgChart> 组件或其父容器具有明确的 widthheight 样式。没有尺寸,图表将无法渲染。
  3. 验证数据格式:检查传递给 setOption 的配置对象中的 series.data 格式是否符合 ECharts 的要求。
  4. 查看初始化错误:在 useEffectecharts.init 的部分添加 try...catch 来捕获任何初始化时抛出的错误。

示例:

// 1. 检查 app/utils/echarts.ts
echarts.use([SVGRenderer,LineChart, // 确保已添加GridComponent,TooltipComponent,
])// 2. 在组件中设置明确的容器尺寸
<SvgChart ref={chartRef} style={{ width: 350, height: 300 }} />

9.2 数据更新不生效

问题:数据更新后图表没有重新渲染

解决方案

  1. 检查useMemo的依赖数组
  2. 确保数据引用发生变化
  3. 验证图表实例是否正确更新
const chartOption = useMemo(() => {// 图表配置
}, [data, theme]) // 确保包含所有依赖useEffect(() => {if (chartInstance && chartOption) {chartInstance.setOption(chartOption, true) // 第二个参数为true表示完全替换}
}, [chartOption])

9.3 性能问题

问题:图表渲染导致性能问题

解决方案

  1. 使用数据采样减少数据点
  2. 实现虚拟滚动
  3. 使用Web Worker处理大量数据
// 数据采样
const sampledData = data.length > 1000 ? data.filter((_, index) => index % 10 === 0): data

9.4 内存泄漏

问题:组件卸载后图表实例未正确清理

解决方案

  1. 在useEffect的清理函数中销毁图表实例
  2. 使用useRef确保引用一致性
useEffect(() => {let chartInstance: ECharts | undefinedif (chartRef.current) {chartInstance = echarts.init(chartRef.current)chartInstance.setOption(chartOption)}return () => {if (chartInstance) {chartInstance.dispose()}}
}, [chartOption])

总结

通过以上步骤,您可以在React Native项目中成功接入ECharts图表。关键要点包括:

  1. 正确的依赖安装和配置
  2. 合理的数据获取和管理
  3. 优化的图表配置和渲染
  4. 完善的错误处理和用户体验
  5. 性能优化和内存管理

这个解决方案提供了一个完整的图表集成框架,可以根据具体需求进行扩展和定制。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/web/87539.shtml
繁体地址,请注明出处:http://hk.pswp.cn/web/87539.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

基于C#的OPCServer应用开发,引用WtOPCSvr.dll

操作流程&#xff1a; 1.引入WtOPCSvr.dll文件 2.注册服务&#xff1a;使用UpdateRegistry方法注册&#xff0c;注意关闭应用时使用UnregisterServer取消注册。 3.初始化服务&#xff1a;使用InitWTOPCsvr初始化 4.使用CreateTag方法&#xff0c;创建标签 5.读写参数使用下面三…

Java类加载器getResource行为简单分析

今天尝试集成一个第三方SDK&#xff0c;在IDE里运行正常&#xff0c;放到服务器上却遇到了NPE&#xff0c;反编译一看&#xff0c;原来在这一行&#xff1a;String path Test.class.getClassLoader().getResource("").getPath(); // Test.class.getClassLoader().ge…

【CodeTop】每日练习 2025.7.4

Leetcode 1143. 最长公共子序列 动态规划解决&#xff0c;比较当前位置目标和实际字符串的字母&#xff0c;再根据不同情况计算接下来的情形。 class Solution {public int longestCommonSubsequence(String text1, String text2) {char[] t1 text1.toCharArray();char[] t2…

ES6从入门到精通:Promise与异步

Promise 基础概念Promise 是 JavaScript 中处理异步操作的一种对象&#xff0c;代表一个异步操作的最终完成或失败及其结果值。它有三种状态&#xff1a;Pending&#xff08;进行中&#xff09;、Fulfilled&#xff08;已成功&#xff09;、Rejected&#xff08;已失败&#xf…

数据结构:二维数组(2D Arrays)

目录 什么是二维数组&#xff1f; 二维数组的声明方式 方式 1&#xff1a;静态二维数组 方式 2&#xff1a;数组指针数组&#xff08;数组中存放的是指针&#xff09; 方式 3&#xff1a;双指针 二级堆分配 &#x1f4a1; 补充建议 如何用“第一性原理”去推导出 C 中…

HAProxy 和 Nginx的区别

HAProxy 和 Nginx 都是优秀的负载均衡工具&#xff0c;但它们在设计目标、适用场景和功能特性上有显著区别。以下是两者的详细对比&#xff1a;1. 核心定位特性HAProxyNginx主要角色专业的负载均衡器/代理Web 服务器 反向代理/负载均衡设计初衷高性能流量分发高并发 HTTP 服务…

基于Java+SpringBoot的健身房管理系统

源码编号&#xff1a;S586源码名称&#xff1a;基于SpringBoot的健身房管理系统用户类型&#xff1a;多角色&#xff0c;用户、教练、管理员数据库表数量&#xff1a;13 张表主要技术&#xff1a;Java、Vue、ElementUl 、SpringBoot、Maven运行环境&#xff1a;Windows/Mac、JD…

【MySQL安装-yum/手动安装,卸载,问题排查处理完整文档(linux)】

一.使用Yum仓库自动安装 步骤1:添加MySQL Yum仓库 sudo rpm -Uvh https://dev.mysql.com/get/mysql80-community-release-el7-6.noarch.rpm步骤2:安装MySQL服务器 sudo yum install mysql-server -y步骤3:启动并设置开机自启 sudo systemctl start mysqld sudo systemct…

自定义线程池-实现任务0丢失的处理策略

设计一个线程池&#xff0c;要求如下&#xff1a;队列最大容量为10&#xff08;内存队列&#xff09;。当队列满了之后&#xff0c;拒绝策略将新的任务写入数据库。从队列中取任务时&#xff0c;若该队列为空&#xff0c;能够从数据库中加载之前被拒绝的任务模拟数据库 (TaskDa…

【NLP入门系列四】评论文本分类入门案例

&#x1f368; 本文为&#x1f517;365天深度学习训练营 中的学习记录博客&#x1f356; 原作者&#xff1a;K同学啊 博主简介&#xff1a;努力学习的22级本科生一枚 &#x1f31f;​&#xff1b;探索AI算法&#xff0c;C&#xff0c;go语言的世界&#xff1b;在迷茫中寻找光芒…

Ubuntu安装ClickHouse

注&#xff1a;本文章的ubuntu的版本为&#xff1a;ubuntu-20.04.6-live-server-amd64。 Ubuntu&#xff08;在线版&#xff09; 更新软件源 sudo apt-get update 安装apt-transport-https 允许apt工具通过https协议下载软件包。 sudo apt-get install apt-transport-htt…

C++26 下一代C++标准

C++26 将是继 C++23 之后的下一个 C++ 标准。这个新标准对 C++ 进行了重大改进,很可能像 C++98、C++11 或 C++20 那样具有划时代的意义。 一:C++标准回顾 C++ 已经有 40 多年的历史了。过去这些年里发生了什么?这里给出一个简化版的答案,直到即将到来的 C++26。 1. C++9…

【MySQL】十六,MySQL窗口函数

在 MySQL 8.0 及以后版本中&#xff0c;窗口函数&#xff08;Window Functions&#xff09;为数据分析和处理提供了强大的工具。窗口函数允许在查询结果集上执行计算&#xff0c;而不必使用子查询或连接&#xff0c;这使得某些类型的计算更加高效和简洁。 语法结构 function_…

微型气象仪在城市环境的应用

微型气象仪凭借其体积小、成本低、部署灵活、数据实时性强等特点&#xff0c;在城市环境中得到广泛应用&#xff0c;能够为城市规划、环境管理、公共安全、居民生活等领域提供精细化气象数据支持。一、核心应用场景1. 城市微气候监测与优化热岛效应研究场景&#xff1a;在城市不…

【仿muduo库实现并发服务器】eventloop模块

仿muduo库实现并发服务器一.eventloop模块1.成员变量std::thread::id _thread_id;//线程IDPoller _poll;int _event_fd;std::vector<Function<Function>> _task;TimerWheel _timer_wheel2.EventLoop构造3.针对eventfd的操作4.针对poller的操作5.针对threadID的操作…

Redis 加锁、解锁

Redis 加锁和解锁的应用 上代码 应用调用示例 RedisLockEntity lockEntityYlb RedisLockEntity.builder().lockKey(TradeConstants.HP_APP_AMOUNT_LOCK_PREFIX appUser.getAccount()).value(orderId).build();boolean isLockedYlb false;try {if (redisLock.tryLock(lockE…

在 Windows 上为 WSL 增加 root 账号密码并通过 Shell 工具连接

1. 为 WSL 设置 root 用户密码 在 Windows 上使用 WSL&#xff08;Windows Subsystem for Linux&#xff09;时&#xff0c;默认情况下并没有启用 root 账号的密码。为了通过 SSH 或其他工具以 root 身份连接到 WSL&#xff0c;我们需要为 root 用户设置密码。 设置 root 密码步…

2730、找到最长的半重复子字符穿

题目&#xff1a; 解答&#xff1a; 窗口为[left&#xff0c;right]&#xff0c;ans为窗口长度&#xff0c;same为子串长度&#xff0c;窗口满足题设条件&#xff0c;即只含一个连续重复字符&#xff0c;则更新ans&#xff0c;否则从左边开始一直弹出&#xff0c;直到满足条件…

MCP Java SDK源码分析

MCP Java SDK源码分析 一、引言 在当今人工智能飞速发展的时代&#xff0c;大型语言模型&#xff08;LLMs&#xff09;如GPT - 4、Claude等展现出了强大的语言理解和生成能力。然而&#xff0c;这些模型面临着一个核心限制&#xff0c;即无法直接访问外部世界的数据和工具。M…

[Linux]内核如何对信号进行捕捉

要理解Linux中内核如何对信号进行捕捉&#xff0c;我们需要很多前置知识的理解&#xff1a; 内核态和用户态的区别CPU指令集权限内核态和用户态之间的切换 由于文章的侧重点不同&#xff0c;上面这些知识我会在这篇文章尽量详细提及&#xff0c;更详细内容还得请大家查看这篇…