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

Compose:1.3 组合、重组作用域和 remember()

文章目录recompose 重组rememberrecompose 性能风险与智能优化、Stablerecompose 智能优化Stable小结总结recompose 重组我们先上一段代码你觉得下面代码最终执行结果是什么setContent{// 注意这里将 MutableState 放在 setContent {} 内varname bymutableStateOf(name)Text(name)lifecycleScope.launch{delay(3000)namevincent}}Text() 最终显示的结果还是 name并没有在 3s 后更新为协程延时后设置的新值。为什么会这样呢实际上上面的代码经过编译器编译后代码类似是这样的// 伪代码setContent{WrapperFunction{varname bymutableStateOf(name)Text(name)lifecycleScope.launch{delay(3000)namevincent}}}被通知刷新的 Text(name) 会被处理为例如被一个 WrapperFunction 包裹起来标记在后续 name 更新的时候就会执行 WrapperFunction 代码块中的代码因为 name 也被包裹在 WrapperFunction所以name 已经不是原先的那个 name而是一个新的 MutableState所以刷新失效了。这个过程触发了 recompose 重组。在 Compose 完成一个 UI 的展示会经过三个步骤组合、布局、绘制相比传统 View 系统多了第一步的组合组合的作用可以简单理解为创建界面对象元素然后就是对界面对象进行测量、摆放、绘制过程最终将 UI 展示出来。在这里说个题外话为什么需要多一个组合的步骤就是为了声明式 UI。再举个例子说明classMainActivity:ComponentActivity(){varname bymutableStateOf(name)override funonCreate(savedInstanceState:Bundle?){setContent{Column{for(c in name.toCharArray()){Text(c.toString())}}}lifecycleScope.launch{delay(3000)namevincent}}}上面的例子很简单将字符拆分到每个 Text3s 后文字变更重新刷新。如果用传统 View 系统我们是需要 ViewGroup.addView() 或 ViewGroup.removeView() 的方式来处理但在声明式 UI 是没有的这种结构性变化的操作要怎么处理呢就是放在组合过程。说回重组重组也是组合的过程这种部分或全部的组合过程称为 recompose 重组。recompose 是有作用范围的伪代码的 WrapperFunction 这个 lambda这个作用范围也称为 recompose scope 重组作用域。remember解决上面的问题也很简单其中一种解决方案是将被通知更新的 Composable 再包裹一层 Composable 即可setContent{varname bymutableStateOf(name)Button(onClick{}){// Text() 被包多一层 Button()重组作用域被限制在 Button() 的 lambda 范围Text(name)}lifecycleScope.launch{delay(3000)namevincent}}不过这种并不是解决方案。所以 Compose 为我们提供了 remember。setContent{// 第一次执行会创建 remember lambda 的 MutableState 对象并保存// 3s 后触发重组时对象没有变化remember 会返回保存的对象而这个保存的对象的值已变为新值varname by remember{mutableStateOf(name)}Text(name)lifecycleScope.launch{delay(3000)namevincent}}remember 起到缓存的作用当第一次执行的时候会将 lambda 代码块的内容执行然后返回结果同时也会保存这个结果后续再调用它的时候如果返回结果相同就不会重复执行直接返回。简单理解就是remember 可以防止由重组而导致的变量的反复初始化。remember 主要用于 recompose 的场景因为 Composable 可能在内部或外部都有可能存在 recompose。那什么时候应该用 remember有以下判断依据识别应该使用 remember在每个 Composable 里面可能会重复计算的处理上例如 mutableStateOf都加上 remember在组合过程外部的不需要用 remember因为放在外面的 mutableStateOf 不会重复初始化也不能用 remember因为 remember 也是一个 Composable另外 remember 是可以带参数的ComposablefunShowCharCount(value:String){val lengthremember{value.length}Text(字符串的长度是 $length)}假设 value.length 是一个可能会重复计算且会影响性能的操作上面的代码使用了 remember 避免了 recompose 重复计算的问题刚刚也说过 remember 相当于一个缓存那如果 value 的值改变了按上面的写法其实还是获取 remember 缓存的旧值这就存在准确性的问题。所以这时候就要使用remember 带 key 的函数在改变时 key 不一样remember 会重新执行然后再缓存起来funShowCharCount(value:String){// 以 value 作为 key如果 value 和上一次 remember 的缓存值不一样了重新执行 lambdaval lengthremember(value){value.length}// remember(value, ....) 支持多个 keyText(字符串的长度是 $length)}remember 可以携带多个参数如果是多个参数共同决定是否重新创建就将这些参数都传给 remember剩下的缓存以及 key 的有效性判断就交给 remember 即可。需要注意的是 remember 只能用在组合重组的过程不能被用在布局、绘制过程这也是 remember 的局限性布局绘制过程会由 Modifier 来解决。recompose 性能风险与智能优化、Stablerecompose 智能优化varname bymutableStateOf(test1)setContent{Column{Text(name,Modifier.clickable{nametest2})}}上面的代码会在点击的时候更新 Text()我们上面有讲过这是 recompose 过程Column 内的 lambda 就是 recompose 的范围。但如果你看 Column 或其他 Composable 函数的源码会发现它们都是 inline 内联函数也就是在编译时 Column 内的 lambda 代码都会被抽离出来铺平recompose 影响的范围就不仅仅是 lambda 内。可以写个 demo 测试varname bymutableStateOf(test1)setContent{println(Recompose 范围测试1)Column{println(Recompose 范围测试2)Text(name,Modifier.clickable{nametest2})}}输出结果 第一次执行Recompose范围测试1Recompose范围测试2点击后Recompose执行Recompose范围测试1Recompose范围测试2上面的代码会在点击 Text() 时都打印输出。看到这或许你会有疑问这样被动 recompose 是否会有性能问题varname bymutableStateOf(test1)setContent{println(Recompose 范围测试1)Column{println(Recompose 范围测试2)Heavy()Text(name,Modifier.clickable{nametest2})}}ComposablefunHeavy(){print(Recompose 范围测试Heavy)Text(Heavy)}输出结果Recompose范围测试1Recompose范围测试2Recompose范围测试Heavy点击后Recompose执行Recompose范围测试1Recompose范围测试2我们写了一个 Heavy()当点击 Text() 时会触发 recompose其他的 Composable 和操作也会被动的 recompose。但上面的案例运行后你会发现Heavy() 内部的代码执行完一次后你再点击没有再执行了。其实 Heavy() 已经被调用但是不执行。原因是 Compose 在编译时会额外对函数添加一些处理其中就有对被动 recompose 的条件判断执行到 Heavy() 时编译器添加的条件判断到 Heavy() 的参数没有更新那就直接跳过否则有参数且参数改变了就会重复执行。因为这里 Heavy() 是没有参数的所以也就只会执行一次。varname bymutableStateOf(test1)setContent{println(Recompose 范围测试1)Column{println(Recompose 范围测试2)Heavy(name)Text(name,Modifier.clickable{nametest2})}}ComposablefunHeavy(text:String){print(Recompose 范围测试Heavy)Text(Heavy: $text)}输出结果Recompose范围测试1Recompose范围测试2Recompose范围测试Heavy点击后Recompose执行Recompose范围测试1Recompose范围测试2Recompose范围测试Heavy如果 Heavy() 添加一个参数参数改变时被动 recompose 时就会被重复执行Heavy() 内部有用到这个参数才会重复执行否则也是不会调用。这是 Compose 的性能优化避免了 recompose 时的被动执行。需要注意的是这种性能优化是为了解决 Compose 自动更新所带来的更新范围过大超过需求的问题跳过没必要的更新相对于传统写法是不存在的因为传统 UI 都是人工手动控制更新这个性能优化并不是和传统 UI 能对比的优势。Stable上面节点讲到 recompose 是做了性能优化会智能跳过参数没改动过的函数避免重复执行如果传入的是一个对象类型是否也可以呢varuserUser(vincent)varname bymutableStateOf(test1)setContent{println(Recompose 范围测试1)Column{println(Recompose 范围测试2)Heavy(user)Text(name,Modifier.clickable{nametest2})}}ComposablefunHeavy(user:User){print(Recompose 范围测试Heavy)Text(Hello ${user.name})}dataclassUser(val name:String)输出结果Recompose范围测试1Recompose范围测试2Recompose范围测试Heavy点击后Recompose执行Recompose范围测试1Recompose范围测试2上面的代码运行后同样的也是能做到智能跳过验证了 Compose 的性能优化不仅是针对基本数据类型也包含对象类型。但是还需要再进一步验证 Compose 是通过哪种方式判断对象是否改变的。在 kotlin 中 与 Java 的 equals() 相同而 kotlin 中 与 Java 的 相同主要就是验证用的哪一种。首先验证 kotlin 的 是否是 Compose 的判断依据varuserUser(vincent)varname bymutableStateOf(test1)setContent{println(Recompose 范围测试1)Column{println(Recompose 范围测试2)Heavy(user)// 点击时 user 不是同一个对象Text(name,Modifier.clickable{nametest2userUser(vincent)// 替换 user 为新对象但字段数值没变})}}ComposablefunHeavy(user:User){print(Recompose 范围测试Heavy)Text(Hello ${user.name})}dataclassUser(val name:String)输出结果Recompose范围测试1Recompose范围测试2Recompose范围测试Heavy点击后Recompose执行Recompose范围测试1Recompose范围测试2上面的执行结果是 Heavy() 没有在 recompose 二次执行说明 Compose 是用的 kotlin 的 也就是 equals 这种结构性相等判断的。varuserUser(vincent)varname bymutableStateOf(test1)setContent{println(Recompose 范围测试1)Column{println(Recompose 范围测试2)Heavy(user)// 点击时 user 不是同一个对象Text(name,Modifier.clickable{nametest2userUser(vincent)// 替换 user 为新对象但字段数值没变})}}ComposablefunHeavy(user:User){print(Recompose 范围测试Heavy)Text(Hello ${user.name})}dataclassUser(varname:String)// 改成了 var输出结果Recompose范围测试1Recompose范围测试2Recompose范围测试Heavy点击后Recompose执行Recompose范围测试1Recompose范围测试2Recompose范围测试Heavy在刚才的基础上把 User 对象的 name 属性由 val 改成 var运行结果是又会二次执行了。这是因为当你把 name 改成 var 时Compose 就会认为 User 是一个不可靠的类此时就会使用 kotlin 的 引用判断User 不是同一个对象就会重复执行。如果将属性改成 var 在未来被修改了而没有执行这将会导致 bug所以 Compose 这么做是为了让程序达到足够的准确性因为准确性比性能更重要。如果你想让不可靠的类也可以让 Compose 认定为可靠继而跳过执行可以通过添加 Stable 注解让 Compose 用结构性相等 equals 判断就行了varuserUser(vincent)varname bymutableStateOf(test1)setContent{println(Recompose 范围测试1)Column{println(Recompose 范围测试2)Heavy(user)Text(name,Modifier.clickable{nametest2})}}ComposablefunHeavy(user:User){print(Recompose 范围测试Heavy)Text(Hello ${user.name})}// 添加了注解告知 Compose 用 equals 判断就行了// 而且要把 data class 换成 class为了保证 hashCode 和 equals 没有被改动StableclassUser(varname:String)输出结果Recompose范围测试1Recompose范围测试2Recompose范围测试Heavy点击后Recompose执行Recompose范围测试1Recompose范围测试2Stable 的使用遵循三个原则现在相等就永远相等确保 equals 没有被重写例如 data class 就会重写当公开属性改变的时候通知到用到这个属性的 Composition公开属性即 Java 的 public在 kotlin 属性默认都是公开的公开属性需要全部是可靠属性即类中的对象类型也要保证是可靠的对象类型内的属性也是可靠的但在 Compose 实际上只会以第二条作为判断依据不满足第二条就会认为是不可靠不稳定的会在 recompose 重复执行。varuserUser(vincent)varname bymutableStateOf(test1)setContent{println(Recompose 范围测试1)Column{println(Recompose 范围测试2)Heavy(user)Text(name,Modifier.clickable{nametest2})}}ComposablefunHeavy(user:User){print(Recompose 范围测试Heavy)Text(Hello ${user.name})}// 添加 Stable 注解更多是用在有声明了 var 属性的接口上// StableclassUser(name:String){// 用代理这种方式注解也可以不用了也能被 Compose 识别为可靠的类// 这种写法在 Compose 很常用这样写也不用去写 Stable 注解varname bymutableStateOf(name)}classUser(name:String,company:Company){varname bymutableStateOf(name)varcompany bymutableStateOf(company)// 因为 Company 不可靠这么写 Compose 也会认为 User 类不可靠}// 这个类是不可靠的classCompany(varaddress:String)小结当类中属性都是 val 声明时Compose 会认为这是一个可靠的类此时 recompose 是通过 equals() 判断是否是同一个对象如果是同一个对象就不会重复执行当类中属性存在 var 声明时Compose 会认为这是一个不可靠的类此时 recompose 是通过 引用判断Compose 基本都会重新执行一遍这是为了确保准确性当类中属性存在 var 声明但希望 Compose 识别是可以可靠的类可以对类添加 Stable 注解但类不能是 data class要保留原始的 hashCode 和 equals由程序员保证可靠性让 recompose 跳过不重复执行或者将 var 属性通过 mutableStateOf 代理也能让 Compose 识别为可靠的类总结一、recompose 重组在 Compose 完成一个 UI 的展示会经过三个步骤组合、布局、绘制组合过程也包含重组这种部分或全部的组合过程称为 recompose 重组重组执行的范围称为 recompose scope 重组作用域二、rememberremember 的作用是防止由重组而导致的变量的反复初始化remember 主要用于 recompose 的场景起到缓存的作用可以携带一个或多个 key 传参决定什么时候重新创建在每个 Composable 里面可能会重复计算的处理上例如 mutableStateOf都加上 remember在组合过程外部的不需要用 remember因为放在外面的 mutableStateOf 不会重复初始化也不能用 remember因为 remember 也是一个 Composable在每个 Composable 里面可能会重复计算的处理上例如 mutableStateOf都加上 remember在组合过程外部的不需要用 remember因为放在外面的 mutableStateOf 不会重复初始化也不能用 remember因为 remember 也是一个 Composableremember 只能用在组合重组的过程不能被用在布局、绘制过程三、recompose 智能优化Compose 在编译时会额外对函数添加一些处理其中就有对被动 recompose 的条件判断判断到 Composable 参数没有更新就直接跳过否则有参数且参数改变了就会重复执行。这种性能优化是为了解决 Compose 自动更新所带来的更新范围过大超过需求的问题跳过没必要的更新。Compose 的智能优化不仅是针对基本数据类型也包含对象类型当类中属性都是 val 声明时Compose 会认为这是一个可靠的类此时 recompose 是通过 equals() 判断是否是同一个对象如果是同一个对象就不会重复执行当类中属性存在 var 声明时Compose 会认为这是一个不可靠的类此时 recompose 是通过 引用判断Compose 基本都会重新执行一遍这是为了确保准确性四、Stable当类中属性存在 var 声明但希望 Compose 识别是可以可靠的类可以对类添加 Stable 注解但类不能是 data class要保留原始的 hashCode 和 equals由程序员保证可靠性让 recompose 跳过不重复执行或者将 var 属性通过 mutableStateOf 代理也能让 Compose 识别为可靠的类。

相关文章:

Compose:1.3 组合、重组作用域和 remember()

文章目录recompose 重组rememberrecompose 性能风险与智能优化、Stablerecompose 智能优化Stable小结总结recompose 重组 我们先上一段代码,你觉得下面代码最终执行结果是什么: setContent {// 注意:这里将 MutableState 放在 setContent {…...

Sciter核心架构深度解析:理解嵌入式UI引擎的工作原理

Sciter核心架构深度解析:理解嵌入式UI引擎的工作原理 【免费下载链接】sciter-sdk Sciter is an embeddable HTML/CSS/scripting engine 项目地址: https://gitcode.com/gh_mirrors/sc/sciter-sdk Sciter是一款功能强大的嵌入式HTML/CSS/脚本引擎&#xff0c…...

神经网络实战技巧:从权重初始化到模型部署优化

1. 神经网络实战技巧综述在咖啡厅里打开笔记本电脑调试神经网络的日子,我总会在键盘旁边放一本翻得卷边的《Neural Tricks of the Trade》。这本书不像传统教材那样堆砌数学公式,而是收录了数十位从业者在实战中总结的"黑科技"。今天我就结合自…...

解锁微软VS Code扩展限制:在非官方编辑器中使用C#/C++扩展

1. 项目概述与背景 如果你是一名深度使用非官方 VS Code 分支(比如 Cursor、VSCodium、Code - OSS)的开发者,那么你很可能在尝试安装微软官方出品的 C# 或 C/C 扩展时,遇到过那个令人沮丧的弹窗:“The C/C extension …...

OpenBullet2配置详解:深入理解每个参数的作用与调优

OpenBullet2配置详解:深入理解每个参数的作用与调优 【免费下载链接】OpenBullet2 OpenBullet reinvented 项目地址: https://gitcode.com/gh_mirrors/op/OpenBullet2 OpenBullet2是一款强大的自动化测试工具,通过灵活的配置参数可以实现各种复杂…...

R语言机器学习数据集处理与建模实战指南

1. 为什么选择R语言处理机器学习数据集?R语言作为统计计算领域的经典工具,在数据处理和可视化方面有着天然优势。CRAN(Comprehensive R Archive Network)上超过15,000个扩展包中,有超过1/3与数据分析和机器学习直接相关…...

怎样通过三维CT查看是否有蛀牙

1 打开weasis-----调整到三视图2 这个时候左边的视图是上视图,因为牙齿有2排,所以需要过滤:--------------调节右下角视图中的红线到上下牙齿的交界处------------此时上视图会只显示出上排的牙齿3 这个时候还是只能确定有虫牙,但…...

RSpec-Rails-Examples自定义匹配器开发:如何创建可读性强的测试断言

RSpec-Rails-Examples自定义匹配器开发:如何创建可读性强的测试断言 【免费下载链接】rspec-rails-examples eliotsykes/rspec-rails-examples: RSpec-Rails-Examples 是一个用于 Rails 应用程序测试的示例库,提供了多种 RSpec 测试的示例和教程&#xf…...

词嵌入技术解析:从Word2Vec到工业应用

1. 词嵌入技术全景解读2013年Word2Vec的横空出世彻底改变了自然语言处理的游戏规则。当时我在处理一个电商评论分类项目,传统TF-IDF方法在语义相似度判断上表现糟糕,直到尝试了词向量——"手机"和"智能手机"的余弦相似度达到0.92&am…...

Geo-Bootstrap实战案例:创建具有90年代魅力的个人作品集网站

Geo-Bootstrap实战案例:创建具有90年代魅力的个人作品集网站 【免费下载链接】geo-bootstrap A timeless Twitter Bootstrap theme built for the modern web. 项目地址: https://gitcode.com/gh_mirrors/ge/geo-bootstrap Geo-Bootstrap是GitHub加速计划中的…...

基于eBPF的ingraind安全监控探针:原理、部署与实战指南

1. 项目概述:基于eBPF的现代安全监控探针如果你在运维一个规模化的容器集群,或者管理着成百上千的Linux服务器,那么“监控”这个词对你来说,可能既熟悉又头疼。熟悉的是,我们离不开CPU、内存、磁盘IO这些基础指标&…...

开源代码生成工具MassGen:模板驱动,解放重复编码生产力

1. 项目概述:一个面向开发者的开源代码生成工具最近在和一些做企业级应用开发的朋友聊天,大家普遍提到一个痛点:面对那些高度重复、模式固定的业务代码(比如增删改查的Controller、Service、DAO层,或者基于数据库表结构…...

Geo-Bootstrap开发者深度指南:源码结构与扩展开发

Geo-Bootstrap开发者深度指南:源码结构与扩展开发 【免费下载链接】geo-bootstrap A timeless Twitter Bootstrap theme built for the modern web. 项目地址: https://gitcode.com/gh_mirrors/ge/geo-bootstrap Geo-Bootstrap是一个为现代Web构建的经典Twit…...

chrome-cdp工作原理解析:如何通过WebSocket与Chrome DevTools协议通信

chrome-cdp工作原理解析:如何通过WebSocket与Chrome DevTools协议通信 【免费下载链接】chrome-cdp-skill Give your AI agent access to your live Chrome session — works out of the box, connects to tabs you already have open 项目地址: https://gitcode.…...

量子纠缠检测的SWAP测试原理与光子芯片实现

1. 量子纠缠检测的核心挑战与SWAP测试原理量子纠缠作为量子计算最独特的资源,其检测与量化一直是量子信息科学的核心课题。传统纠缠见证方法通常需要完整量子态层析,这随系统规模呈指数级增长的计算复杂度严重制约了实际应用。而基于SWAP测试的两比特纠缠…...

Motor Admin与现有系统集成:无缝对接企业应用生态

Motor Admin与现有系统集成:无缝对接企业应用生态 【免费下载链接】motor-admin Deploy a no-code admin panel for any application in less than a minute. Search, create, update, and delete data entries, create custom actions, and build reports. 项目地…...

开源代码审计工具opencode:基于异常检测的智能安全扫描实践

1. 项目概述:一个开源代码审计与异常检测工具最近在跟几个做安全开发的朋友聊天,大家普遍提到一个痛点:项目大了,代码库动辄几十万行,每次上线前的人工代码审计(Code Review)都像大海捞针&#…...

Dantotsu常见问题解答:解决登录失败、下载错误与性能优化技巧

Dantotsu常见问题解答:解决登录失败、下载错误与性能优化技巧 【免费下载链接】Dantotsu Anilist client based on Saikou 项目地址: https://gitcode.com/gh_mirrors/da/Dantotsu Dantotsu是一款基于Saikou的Anilist客户端,为动漫爱好者提供便捷…...

ARM1020E处理器勘误与硬件调试实战指南

1. ARM1020E Rev1处理器勘误深度解析作为一名长期从事ARM架构开发的工程师,我深知处理器勘误(Errata)对系统稳定性的关键影响。今天我将结合ARM1020E Rev1的实际案例,分享三类勘误的处理经验,特别是硬件调试中的典型问…...

GAN七日实战:从原理到PyTorch实现

1. 生成对抗网络入门指南:7天速成实战路线第一次接触GAN时,我被它生成的人脸图片震撼得说不出话——那些根本不存在的人像,连皮肤纹理和发丝都栩栩如生。作为计算机视觉领域的革命性技术,生成对抗网络(GAN)…...

Preact高阶组件:逻辑复用的终极设计模式指南

Preact高阶组件:逻辑复用的终极设计模式指南 【免费下载链接】preact ⚛️ Fast 3kB React alternative with the same modern API. Components & Virtual DOM. 项目地址: https://gitcode.com/gh_mirrors/pr/preact 在现代前端开发中,高效的…...

如何快速掌握Preact:从零开始的现代前端框架完整指南

如何快速掌握Preact:从零开始的现代前端框架完整指南 【免费下载链接】preact ⚛️ Fast 3kB React alternative with the same modern API. Components & Virtual DOM. 项目地址: https://gitcode.com/gh_mirrors/pr/preact Preact是一个仅4kB大小的现代…...

正则表达式终极指南:10个文本处理匹配技巧

正则表达式终极指南:10个文本处理匹配技巧 【免费下载链接】interview 📚 C/C 技术面试基础知识总结,包括语言、程序库、数据结构、算法、系统、网络、链接装载库等知识及面试经验、招聘、内推等信息。This repository is a summary of the b…...

如何快速定制Material Design Lite主题:掌握SCSS变量与颜色系统的终极指南

如何快速定制Material Design Lite主题:掌握SCSS变量与颜色系统的终极指南 【免费下载链接】material-design-lite Material Design Components in HTML/CSS/JS 项目地址: https://gitcode.com/gh_mirrors/ma/material-design-lite Material Design Lite&…...

CGraph扩展开发指南:如何自定义节点与适配器

CGraph扩展开发指南:如何自定义节点与适配器 【免费下载链接】CGraph 【A common used C & Python DAG framework】 一个通用的、无三方依赖的、跨平台的、收录于awesome-cpp的、基于流图的并行计算框架。欢迎star & fork & 交流 项目地址: https://g…...

掌握Noto Emoji:构建跨平台表情符号的终极视觉工具箱

掌握Noto Emoji:构建跨平台表情符号的终极视觉工具箱 【免费下载链接】noto-emoji Noto Emoji fonts 项目地址: https://gitcode.com/gh_mirrors/no/noto-emoji 当你发送一个笑脸表情时,是否曾想过它如何在iPhone、Android和Windows电脑上保持完全…...

智能体技能开发实战:从工具调用到系统架构的完整指南

1. 项目概述与核心价值最近在探索智能体(Agent)开发时,我发现了一个宝藏仓库:heilcheng/awesome-agent-skills。这不仅仅是一个简单的列表,而是一个由社区驱动的、关于智能体“技能”的精选知识库。简单来说&#xff0…...

langsmith-fetch技能:调试LangChain和LangGraph代理的必备工具

langsmith-fetch技能:调试LangChain和LangGraph代理的必备工具 【免费下载链接】awesome-codex-skills A curated list of practical Codex skills for automating workflows across the Codex CLI and API. 项目地址: https://gitcode.com/GitHub_Trending/aw/aw…...

Spring Boot Demo快速入门:5分钟搭建第一个HelloWorld应用

Spring Boot Demo快速入门:5分钟搭建第一个HelloWorld应用 【免费下载链接】spring-boot-demo 🚀一个用来深入学习并实战 Spring Boot 的项目。 项目地址: https://gitcode.com/gh_mirrors/sp/spring-boot-demo Spring Boot Demo是一个用来深入学…...

如何设计高效政务办理系统:React Router路由架构终极指南

如何设计高效政务办理系统:React Router路由架构终极指南 【免费下载链接】react-router Declarative routing for React 项目地址: https://gitcode.com/GitHub_Trending/re/react-router 在数字化政务服务快速发展的今天,如何构建一个流畅、直观…...