当前位置: 首页 > news >正文

【DataLoom】智能问数 - 自然语言与数据库交互

探索DataLoom的智能问数功能:简化数据库查询

在数据驱动的决策制定中,数据库查询是获取洞察的关键步骤。但是,传统的数据库查询方法往往复杂且技术性强,这限制了非技术用户的使用。DataLoom的智能问数功能正是为了解决这一问题而设计的。本文将详细介绍这一功能,并展示其背后的代码实现。

DataLoom简介

DataLoom是一个创新的数据管理平台,旨在通过提供直观的界面和强大的后端处理能力,简化数据查询和分析过程。我们的目标是让数据查询变得简单,让每个人都能轻松地从数据中获取洞察。

智能问数功能

在这里插入图片描述

在这里插入图片描述

智能问数是DataLoom的核心功能之一,它允许用户通过自然语言输入查询请求,系统会自动将其转换为SQL语句并执行。这一功能极大地降低了技术门槛,使得即使是没有数据库背景的用户也能快速获取所需数据。

核心流程图

在这里插入图片描述

核心代码
ChatForSQLRequest类
@Data
public class ChatForSQLRequest {/*** 模型Id*/private Long chatId;/*** 询问的数据*/private String question;
}

这是一个简单的Java Bean类,用于封装用户请求智能问数时发送的数据。它包含两个属性:chatId(模型Id)和question(询问的数据)。

userChatForSQL方法
public void userChatForSQL(ChatForSQLRequest chatForSQLRequest, User loginUser) {Long chatId = chatForSQLRequest.getChatId();String question = chatForSQLRequest.getQuestion();// 1. 获取模型IDChat chat = chatService.getById(chatId);ThrowUtils.throwIf(chat == null, ErrorCode.PARAMS_ERROR, "不存在该助手");// 2. 获取数据源所有的元数据Long datasourceId = chat.getDatasourceId();List<AskAIWithDataTablesAndFieldsRequest> dataTablesAndFieldsRequests = getAskAIWithDataTablesAndFieldsRequests(loginUser, datasourceId);// 3. 构造请求AI的输入String input = buildAskAISQLInput(dataTablesAndFieldsRequests, question);// 4. 持久化消息ChatHistory user_q = new ChatHistory();user_q.setChatRole(ChatHistoryRoleEnum.USER.getValue());user_q.setChatId(chatId);user_q.setModelId(chat.getModelId());user_q.setContent(question);chatHistoryService.save(user_q);// 5. 利用webSocket发送消息通知开始AskSQLWebSocketMsgVO askSQLWebSocketMsgVO = new AskSQLWebSocketMsgVO();askSQLWebSocketMsgVO.setType("start");askSQLWebSocket.sendOneMessage(loginUser.getId(), askSQLWebSocketMsgVO);// 6. 询问AI,获取返回的SQLString sql = aiManager.doAskSQLWithKimi(input, LIMIT_RECORDS);// 7. 执行SQL,并得到返回的结果QueryAICustomSQLVO queryAICustomSQLVO = null;try {queryAICustomSQLVO = buildUserChatForSqlVO(datasourceId, sql);} catch (Exception e) { // 防止异常发生,前端还继续等待接收数据if (e instanceof SQLException) { // 记录异常queryAICustomSQLVO = new QueryAICustomSQLVO();queryAICustomSQLVO.setSql(sql);ChatHistory chatHistory = ChatHistory.builder().chatRole(ChatHistoryRoleEnum.MODEL.getValue()).chatId(chatId).modelId(chat.getModelId()).status(ChatHistoryStatusEnum.FAIL.getValue()).execMessage("查询异常").content(JSONUtil.toJsonStr(queryAICustomSQLVO)).build();chatHistoryService.updateById(chatHistory);}notifyMessageEnd(loginUser.getId());return;}// 8. 将查询的结果存放在数据库中ChatHistory chatHistory = new ChatHistory();chatHistory.setChatRole(ChatHistoryRoleEnum.MODEL.getValue());chatHistory.setChatId(chatId);chatHistory.setModelId(chat.getModelId());// 9. 存储结果类JSON字符串chatHistory.setContent(JSONUtil.toJsonStr(queryAICustomSQLVO));try {chatHistoryService.save(chatHistory);} catch (Exception e) {notifyMessageEnd(loginUser.getId());return;}// 10. 利用webSocket发送消息通知AskSQLWebSocketMsgVO res = AskSQLWebSocketMsgVO.builder().res(queryAICustomSQLVO.getRes()).columns(queryAICustomSQLVO.getColumns()).type("running").sql(sql).build();askSQLWebSocket.sendOneMessage(loginUser.getId(), res);// 11. 通知结束notifyMessageEnd(loginUser.getId());
}

这个方法是处理用户SQL查询请求的核心逻辑。它执行以下步骤:

  1. 验证模型ID是否存在。
  2. 获取数据源的所有元数据。
  3. 构造请求AI的输入。
  4. 持久化用户的消息。
  5. 通过WebSocket通知前端开始处理。
  6. 询问AI,获取返回的SQL语句。
  7. 执行SQL并获取结果。
  8. 将查询结果持久化。
  9. 存储结果类为JSON字符串。
  10. 通过WebSocket发送查询结果。
  11. 通知查询结束。
getAskAIWithDataTablesAndFieldsRequests方法
/*** 查询对应数据源所有元数据(表信息、表字段)* @param loginUser* @param datasourceId* @return*/
private List<AskAIWithDataTablesAndFieldsRequest> getAskAIWithDataTablesAndFieldsRequests(User loginUser, Long datasourceId) {List<CoreDatasetTable> tables = coreDatasourceService.getTablesByDatasourceId(datasourceId, loginUser);ThrowUtils.throwIf(tables.isEmpty(), ErrorCode.PARAMS_ERROR, "数据源暂无数据");List<AskAIWithDataTablesAndFieldsRequest> dataTablesAndFieldsRequests = new ArrayList<>();tables.forEach(table -> {// 查询所有字段LambdaQueryWrapper<CoreDatasetTableField> wrapper = new LambdaQueryWrapper<>();wrapper.eq(CoreDatasetTableField::getDatasetTableId, table.getId());List<CoreDatasetTableField> tableFields = coreDatasetTableFieldService.list(wrapper);AskAIWithDataTablesAndFieldsRequest askAIWithDataTablesAndFieldsRequest = AskAIWithDataTablesAndFieldsRequest.builder().tableId(table.getId()).tableComment(table.getName()).tableName(table.getTableName()).coreDatasetTableFieldList(tableFields).build();dataTablesAndFieldsRequests.add(askAIWithDataTablesAndFieldsRequest);});return dataTablesAndFieldsRequests;
}

这个方法用于查询给定数据源的所有表信息和表字段。它遍历所有表,为每个表查询字段信息,并构建一个包含这些信息的请求列表。

buildAskAISQLInput方法
/*** 构造智能问数的问题* @param dataTablesAndFieldsRequests 数据源元数据* @param question* @return* 示例:* 分析需求:%s,* [* {表名: %s, 表注释: %s, 字段列表:[{%s}、{%s}]}* {表名: %s, 表注释: %s, 字段列表:[{%s}、{%s}]}* ]*/
private String buildAskAISQLInput(List<AskAIWithDataTablesAndFieldsRequest> dataTablesAndFieldsRequests, String question) {StringBuilder res = new StringBuilder();// 1. 构造需求res.append(String.format(ANALYSIS_QUESTION, question));res.append(SPLIT);// 2. 构造表与字段信息StringBuilder tablesAndFields = new StringBuilder();dataTablesAndFieldsRequests.forEach(tableAndFields -> {// 构造当前表字段列表StringBuilder tableFieldsInfo = new StringBuilder();List<CoreDatasetTableField> fieldList = tableAndFields.getCoreDatasetTableFieldList();fieldList.forEach(field -> {tableFieldsInfo.append(String.format(FIELDS_INFO, field.getOriginName(), field.getName(), field.getType()));tableFieldsInfo.append(SPLIT);});// 构造当前表信息String tableFieldsInfoList = String.format(LIST_INFO, tableFieldsInfo);tablesAndFields.append(String.format(TABLE_INFO, tableAndFields.getTableName(), tableAndFields.getTableComment(), tableFieldsInfoList));tableFieldsInfo.append(SPLIT);});res.append(String.format(TABLES_AND_FIELDS_PART, tablesAndFields));return res.toString();
}

这个方法用于构造智能问数的问题。它将用户的问题和数据源的元数据结合起来,形成一个格式化的字符串,该字符串将作为AI的输入。

doAskSQLWithKimi方法
/*** 执行智能问数* @param message 构造的输入* @param limitSize select 结果限制的行数* @return*/
public String doAskSQLWithKimi(String message, int limitSize) {String SQLPrompt = "你是一个MySQL数据库专家,专门负责根据查询需求得出SQL查询语句,接下来我会按照以下固定格式给你提供内容: \n" +"分析需求:{分析需求或者目标} \n" +"所有的数据表元数据:[{数据库表名、表注释、数据库表的字段、注释以及类型}] \n" +"请根据这两部分内容,按照以下指定格式生成内容(此外不要输出任何多余的开头、结尾、注释),并且只生成Select语句!!!, 请严格按照数据表元数据中存在的数据表和字段,不要查询不存在的表和字段\n" +"要求select的结果不超过" + limitSize + "行";List<Message> messages = CollUtil.newArrayList(new Message(RoleEnum.system.name(), SQLPrompt),new Message(RoleEnum.user.name(), message));return moonshotAiClient.chat("moonshot-v1-32k",messages);
}

这个方法用于执行智能问数。它构造一个包含分析需求和数据表元数据的消息,然后通过调用AI客户端来获取SQL查询语句。

buildUserChatForSqlVO方法
/*** 执行SQL并封装智能问数返回类* @param datasourceId 数据源id* @param sql 执行sql* @return 智能问数返回类*/
private QueryAICustomSQLVO buildUserChatForSqlVO(Long datasourceId, String sql) throws SQLException {return datasourceEngine.execSelectSqlToQueryAICustomSQLVO(datasourceId, sql);
}

这个方法用于执行SQL语句并将结果封装到QueryAICustomSQLVO对象中。它调用execSelectSqlToQueryAICustomSQLVO方法,传入数据源ID和SQL语句,然后返回查询结果。

execSelectSqlToQueryAICustomSQLVO方法
/*** 执行SQL语句并将列集合和记录犯规* @param datasourceId 数据源id* @param sql sql语句* @param parameters 参数* @return*/
public QueryAICustomSQLVO execSelectSqlToQueryAICustomSQLVO(Long datasourceId, String sql, Object... parameters) throws SQLException {int dsIndex = (int) (datasourceId % (dataSourceMap.size()));// 获取对应连接池DataSource dataSource = dataSourceMap.get(dsIndex);QueryAICustomSQLVO queryAICustomSQLVO = new QueryAICustomSQLVO();// 所有列List<String> columns = new ArrayList<>();// 所有结果List<Map<String, Object>> res = new ArrayList<>();Connection connection = dataSource.getConnection();PreparedStatement preparedStatement = connection.prepareStatement(sql);// Set parameters to prevent SQL injectionfor (int i = 0; i < parameters.length; i++) {preparedStatement.setObject(i + 1, parameters[i]);}ResultSet rs = preparedStatement.executeQuery();// Execute the query or update// 处理查询结果ResultSetMetaData rsmd = rs.getMetaData();int columnCount = rsmd.getColumnCount();for (int i = 1; i <= columnCount; i++) {columns.add(rsmd.getColumnName(i));}while (rs.next()) {Map<String, Object> resMap = new HashMap<>();for (int i = 1; i <= columnCount; i++) {resMap.put(rsmd.getColumnName(i), rs.getString(i));}res.add(resMap);}queryAICustomSQLVO.setSql(sql);queryAICustomSQLVO.setColumns(columns);queryAICustomSQLVO.setRes(res);return queryAICustomSQLVO;
}

这个方法用于执行SQL查询并将结果集转换为一个包含列名和记录的QueryAICustomSQLVO对象。它使用PreparedStatement来设置参数,执行查询,并遍历结果集,将每一行的数据存储到一个Map中,然后将这些Map添加到结果列表中。

这些代码片段共同构成了DataLoom智能问数功能的核心实现。每个片段都扮演着处理用户请求、与数据库交互、以及与AI服务通信的重要角色。

未来展望

我们对DataLoom的未来充满期待。我们计划引入更多的智能功能,这些功能将在下面的几篇文章中介绍,例如智能仪表盘智能图表分析报告

项目快速启动
  • 见GitHub:DataLoom 仓库
  • 见Gitee地址:Gitee 仓库
如何贡献

如果你对 DataLoom 感兴趣并想做出贡献,欢迎提交 issue 或 Pull Request。我们非常欢迎开发者一起加入,共同改进这个项目。

  • GitHub 地址:DataLoom 仓库
  • Gitee地址:Gitee 仓库
  • 你可以通过创建 Issue 来报告问题,或通过提交 PR 来贡献代码。

希望这篇文章能够激发你对 DataLoom 项目的兴趣!如果你喜欢这个项目,请给我们一个 Star ⭐️,这对我们来说意义重大!

请持续关注,后续文章也会发一些有关项目功能设计亮点介绍

项目地址:DataLoom GitHub 仓库

项目问题通过下面的联系方式进行沟通
邮箱:hardork@163.com
WX号: _hardork

如果需要项目文档📄,可以联系WX号

相关文章:

【DataLoom】智能问数 - 自然语言与数据库交互

探索DataLoom的智能问数功能&#xff1a;简化数据库查询 在数据驱动的决策制定中&#xff0c;数据库查询是获取洞察的关键步骤。但是&#xff0c;传统的数据库查询方法往往复杂且技术性强&#xff0c;这限制了非技术用户的使用。DataLoom的智能问数功能正是为了解决这一问题而…...

【Linux】进程地址空间(初步了解)

文章目录 1. 奇怪的现象2. 虚拟地址空间3. 关于页表4. 为什么要有虚拟地址 1. 奇怪的现象 我们先看一个现象&#xff1a; 为什么父子进程从“同一块地址中”读取到的值不一样呢&#xff1f; 因为这个地址不是物理内存的地址 &#xff0c;如果是物理内存的地址是绝对不可能出…...

hdu-6024

hdu-6024 struct node {int x, c;bool operator<(const node &a) const{return x < a.x;} }; // dp[i][0]为到第i个教室且第i个教室不建糖果店的花费前缀和&#xff0c;dp[i][1]为到第i个教室且第i个教室建糖果店的花费前缀和 int dp[N][2]; void solve() {int n;wh…...

jmeter操作数据库

jmeter操作数据库 一、打开数据库 二、jmeter下载驱动&#xff0c;安装jdbc驱动 1、下载好的驱动包 2、将驱动包复制粘贴 存放在包的路径下 &#xff08;1&#xff09;jdk下面 a、路径&#xff1a;jdk1\jre\lib b、jdk1\jre\lib\ext &#xff08;2&#xff09;jmeter下 a、…...

Stable Diffusion绘画 | 如何做到不同动作表情,人物角色保持一致性(上篇)

由于 SD 具有强大的可控性&#xff0c;在固定人物角色方面&#xff0c;SD 是远超 MJ 的&#xff0c; 其中最好用&#xff0c;也是最优先的方法就是训练一个自己专属的角色模型&#xff0c;例如之前使用秋叶训练器得到的 LoRA模型。 另外&#xff0c;如果不想自己训练模型的话…...

中国计量大学《2023年801+2023年819自动控制原理真题》 (完整版)

本文内容&#xff0c;全部选自自动化考研联盟的&#xff1a;《中国计量大学801819自控考研资料》的真题篇。后续会持续更新更多学校&#xff0c;更多年份的真题&#xff0c;记得关注哦~ 目录 2023年801真题 2023年819真题 Part1&#xff1a;2023年完整版真题 2023年801真题…...

本地运行LLama 3.2的三种方法

大型语言模型&#xff08;LLMs&#xff09;已经彻底改变了AI领域&#xff0c;小型模型也在崛起。因此&#xff0c;即使是在旧的PC和智能手机上运行先进的LLMs也成为了可能。为了给大家一个起点&#xff0c;我们将探索三种不同的方法来本地与LLama 3.2进行交互。 先决条件 在我…...

基于单片机的温度和烟雾检测

目录 一、主要功能 二、硬件资源 三、程序编程 四、实现现象 一、主要功能 基于51单片机&#xff0c;采用DS18B20读取温度&#xff0c;滑动变阻器链接ADC0832数模转换模拟烟雾&#xff0c; 通过lcd1602显示屏显示&#xff0c; 超过阈值则对应的led灯亮起&#xff0c;蜂鸣器…...

利士策分享,探寻中华民族的精神纽带

利士策分享&#xff0c;探寻中华民族的精神纽带 在历史的长河中&#xff0c;中华民族以其独特的文化魅力和坚韧不拔的民族精神&#xff0c;屹立于世界民族之林。 这份力量&#xff0c;源自何处&#xff1f;或许&#xff0c;正是那份纯真的情&#xff0c;如同纽带一般&#xff…...

JAVA思维提升案例3

需求&#xff1a; 某系统的数字密码是一个四位数&#xff0c;如1983&#xff0c;为了安全&#xff0c;需要加密后再传输&#xff0c;加密规则是&#xff1a;对密码中的每位数&#xff0c;都加5 ,再对10求余&#xff0c;最后将所有数字顺序反转&#xff0c;得到一串加密后的新数…...

vscode配置golang

1.安装golang解释器 从网址https://go.dev/dl/下载对应的golang解释器 2.配置环境 Extensions中搜索安装go 2.配置settings.json {"go.autocompleteUnimportedPackages": true,"go.gocodeAutoBuild": false,"explorer.confirmPasteNative"…...

设计模式之原型模式(通俗易懂--代码辅助理解【Java版】)

文章目录 设计模式概述1、原型模式2、原型模式的使用场景3、优点4、缺点5、主要角色6、代码示例7、总结题外话关于使用序列化实现深拷贝 设计模式概述 创建型模式&#xff1a;工厂方法、抽象方法、建造者、原型、单例。 结构型模式有&#xff1a;适配器、桥接、组合、装饰器、…...

Study-Oracle-10-ORALCE19C-RAC集群维护

一路走来&#xff0c;所有遇到的人&#xff0c;帮助过我的、伤害过我的都是朋友&#xff0c;没有一个是敌人。 一、RAC的逻辑架构与进程 1、RAC 与单实例进程的对比 2、RAC相关进程功能 3、在主机查看RAC进程 其他的不列举了 4、RAC集群启停命令 检查集群状态 ORACLE 19C …...

【无题】夜入伊人笑愉,泪湿心夜难眠。

在这句诗中&#xff0c;意境描绘了一种深沉的情感体验&#xff0c;充满了温柔与哀愁。诗人通过“夜入伊人笑愉”开启了一段梦境之旅&#xff0c;其中“夜入”象征着进入梦境的状态。在这个梦幻的世界里&#xff0c;诗人与心爱的人欢笑嬉戏&#xff0c;那份快乐和亲昵如同真实的…...

docker下载mysql时出现Unable to pull mysql:latest (HTTP code 500) server error 问题

报错 Unable to pull mysql:latest (HTTP code 500) server error - Get “https://registry-1.docker.io/v2/”: EOF 解决方法 将VPN开到Global模式 解决啦...

厦门网站设计的用户体验优化策略

厦门网站设计的用户体验优化策略 在信息化快速发展的今天&#xff0c;网站作为企业与用户沟通的重要桥梁&#xff0c;用户体验&#xff08;UX&#xff09;的优化显得尤为重要。尤其是在交通便利、旅游资源丰富的厦门&#xff0c;吸引了大量企业进驻。在这样竞争激烈的环境中&am…...

Fastjson反序列化

Fastjson反序列化一共有三条利用链 TempLatesImpl&#xff1a;实战中不适用JdbcRowSetImpl&#xff1a;实际运用中较为广泛BasicDataSource&#xff08;BCEL&#xff09; 反序列化核心 反序列化是通过字符串或字节流&#xff0c;利用Java的反射机制重构一个对象。主要有两种…...

Python Linux解压安装脚本

本脚本用于安装python3.x, 需要指定python版本&#xff0c;如12代表3.12 安装文件下载自 python-build-standalone 我下载的文件后缀是&#xff1a;-x86_64-unknown-linux-gnu-pgo-full.tar.zst&#xff0c;根据需要自行下载 注意&#xff1a;install_only或tar.gz包的目录没有…...

numpy 逻辑运算方法介绍

在 NumPy 中&#xff0c;逻辑运算方法用于对数组中的元素进行逻辑操作&#xff0c;通常用于布尔数组&#xff0c;也可用于数值数组&#xff0c;非零值视为 True&#xff0c;零值视为 False。常见的逻辑运算方法有&#xff1a; 1. numpy.logical_and 逐元素进行逻辑与运算&…...

怎么查看网站是否被谷歌收录,查看网站是否被谷歌收录的简便方法

查看网站是否被谷歌收录&#xff0c;有多种简便方法可供选择。以下是一些常用的简便方法&#xff1a; 一、使用“site:”指令 打开谷歌搜索引擎&#xff1a; 在浏览器中打开Google.com&#xff0c;确保使用的是谷歌的官方搜索引擎。 输入查询指令&#xff1a; 在搜索框中输…...

【前端开发入门】前端开发环境配置

目录 引言一、Vscode编辑器安装1. 软件下载2. 软件安装3. 插件安装 二、Nodejs环境安装及版本控制1. 安装内容2. 使用nvm安装2.1 软件下载并安装2.2 nvm基本指令2.3 nvm下载过慢导致超时解决 三、git安装及配置1. 软件下载2. 软件安装3. 基础配置 四、总结 引言 本系列教程旨在…...

Windows驱动开发(二)

1. NT和WDM式驱动 1. NT式驱动 传统的Windows系统驱动类型。NT式驱动的启动/停止/安装/卸载只能由 服务控制管理程序组件(SCM) 来完成的。 包括最简单的hello world&#xff0c;以及目前常用的文件过滤框架 minifilter 都是基于NT式实现的。 NT式驱动的最大特点即完全不依赖硬…...

Hotspot是什么?

Hotspot 简单来说&#xff0c;JVM的一种。 一、HotSpot 的官方定义 HotSpot 是 Oracle 公司开发的一个高性能的 Java 虚拟机&#xff08;JVM&#xff09;。它通过一系列先进的技术和优化手段&#xff0c;为 Java 应用程序提供高效的运行环境&#xff0c;实现了跨平台的代码执行…...

k8s-集群部署1

k8s-集群部署1 一、基础环境准备二、docker环境准备三、k8s集群部署1.kubeadm创建集群2.使用kubeadm引导集群 总结 一、基础环境准备 首先&#xff0c;需要准备三个服务器实例&#xff0c;这里我使用了阿里云创建了三个实例&#xff0c;如果不想花钱&#xff0c;也可以在VM上创…...

wordpress Contact form 7发件人邮箱设置

此教程仅适用于演示站有留言的主题&#xff0c;演示站没有留言的主题&#xff0c;就别往下看了&#xff0c;免费浪费时间。 使用了Contact form 7插件的简站WordPress主题&#xff0c;在有人留言时&#xff0c;就会发邮件到网站的系统邮箱(一般与管理员邮箱为同一个)里。上面显…...

15分钟学 Python 第38天 :Python 爬虫入门(四)

Day38 : Python爬虫异常处理与反爬虫机制 章节1&#xff1a;异常处理的重要性 在爬虫开发过程中&#xff0c;网络请求和数据解析常常会遭遇各种异常。正确的异常处理可以提高程序的稳定性&#xff0c;避免崩溃&#xff0c;并帮助开发者快速定位问题。 章节2&#xff1a;常见…...

GWAS分析中显著位点如何注释基因:excel???

大家好&#xff0c;我是邓飞。 今天星球的小伙伴问了一个问题&#xff1a; 我现在在做GWAS分析&#xff0c;现在已经找到性状关联的SNP位点&#xff0c;下一步我如何根据position 找到基因呢&#xff1f; 关于基因注释&#xff0c;之前写过一些博客&#xff0c;可以用到的软件…...

深入浅出 CSS 定位:全面解析与实战指南

“批判他人总是想的太简单 剖析自己总是想的太困难” 文章目录 目录 前言文章有误敬请斧正 不胜感恩&#xff01;1. CSS 定位概述2. 定位类型详解2.1 static&#xff08;默认定位&#xff09;2.2 relative&#xff08;相对定位&#xff09;2.3 absolute&#xff08;绝对定位&am…...

HTTPS协议详解:从原理到流程,全面解析安全传输的奥秘

&#x1f49d;&#x1f49d;&#x1f49d;欢迎莅临我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐&#xff1a;「storm…...

Android 13.0 系统内存优化之修改dalvik虚拟机的内存参数

1.前言 在13.0的系统rom开发定制中,app应用也是运行在dalvik虚拟机上的,所以对于一些内存低的系统中,在某些大应用会出现耗内存 卡顿情况,这是系统分配的内存不够大,在进行耗内存的操作,就会出现频繁gc等等原因造成不流畅的现象,接下来就分析下 虚拟机分配内存的相关原理…...