
前端【免费下载链接】getxOpen screens/snackbars/dialogs/bottomSheets without context, manage states and inject dependencies easily with Get.项目地址https://gitcode.com/gh_mirrors/ge/getx点击查看免费下载GetX 是 Flutter 生态中一个轻量而强大的微框架将高性能状态管理、智能依赖注入与便捷路由管理整合在同一个包中并支持免 context 操作 snackbar、dialog、bottomSheet 与国际化、主题切换等实用能力。本文以本仓库 README.zh-cn.md 为骨架结合仓库源码与示例工程系统讲解从安装、26 行计数器示例到三大核心功能、GetConnect 网络层、GetPage 中间件与高级 API 的完整用法读完后你可以直接在自己的 Flutter 项目中落地一套「界面、逻辑、依赖、路由完全解耦」的开发范式。关于 GetX三大基本原则GetX 的定位是 Flutter 上的轻量且强大的多端解决方案官方在 README 中明确了三个基本原则性能专注于性能与最小资源消耗。由于整个框架由多个独立模块组成见 lib/get.dart 的 export 结构如果你只用状态管理则只有状态管理模块被编译进产物未使用的模块不会进入你的代码。效率语法极其简捷同时保持高性能可显著缩短开发时长。结构将界面、逻辑、依赖和路由完全解耦使代码更易维护。从源码结构看lib/get.dart 将功能拆分为get_core、get_instance、get_navigation、get_rx、get_state_manager、get_utils、get_connect、get_animations等独立容器这正对应 README 所说的「功能都在独立容器中使用后才启动」。GetX 可以在 Android、iOS、Web、Mac、Linux、Windows 上以相同代码运行配合 Get Server 可在后端复用前端代码配合 Get CLI 可自动化整个开发流程。安装将 Get 添加到pubspec.yamldependencies: get:在需要使用的文件中导入import package:get/get.dart;GetX 计数器示例26 行完成状态路由共享Flutter 默认计数器项目有 100 多行而使用 GetX 重写一个「计数器 Plus 版」只需26 行含注释实现每次点击改变状态、页面切换、跨页面共享状态、业务逻辑与界面分离。步骤 1将MaterialApp替换为GetMaterialApp。void main() runApp(GetMaterialApp(home: Home()));注意GetMaterialApp并不是修改后的MaterialApp而是一个预配置的 Widget其子组件是默认的MaterialApp。它会创建路由、注入依赖、注入翻译等。如果只用 Get 做状态管理或依赖管理则没有必要使用GetMaterialApp只有使用路由管理Get.to()、Get.back()等时才需要它。步骤 2创建业务逻辑类用.obs让任意变量变为可观察class Controller extends GetxController{ var count 0.obs; increment() count; }步骤 3创建界面使用StatelessWidget即可无需StatefulWidgetclass Home extends StatelessWidget { override Widget build(context) { // 使用Get.put()实例化你的类使其对当下的所有子路由可用。 final Controller c Get.put(Controller()); return Scaffold( // 使用Obx(()每当改变计数时就更新Text()。 appBar: AppBar(title: Obx(() Text(Clicks: ${c.count}))), // 用一个简单的Get.to()即可代替Navigator.push那8行无需上下文 body: Center(child: ElevatedButton( child: Text(Go to Other), onPressed: () Get.to(Other()))), floatingActionButton: FloatingActionButton(child: Icon(Icons.add), onPressed: c.increment)); } } class Other extends StatelessWidget { // 你可以让Get找到一个正在被其他页面使用的Controller并将它返回给你。 final Controller c Get.find(); override Widget build(context){ // 访问更新后的计数变量 return Scaffold(body: Center(child: Text(${c.count}))); } }三大核心功能状态管理Get 提供了两个不同的状态管理器简单的状态管理器GetBuilder和响应式状态管理器GetX / Obx。二者在 lib/get_state_manager 中实现其中 get_controllers.dart 定义了GetxController——它合并了原先的 RxController 与 GetBuilder 用法update()方法会通知监听者刷新 UI支持按ids精确刷新或通过condition条件控制是否刷新。响应式状态管理器GetX 将响应式编程变得极其简单不需要创建StreamControllers不需要为每个变量创建StreamBuilder不需要为每个状态创建类不需要为一个初始值创建 getter把普通变量变为可观察只需在末尾加上.obsvar name Jonatas Borges.obs;在 UI 中监听值变化并自动更新Obx(() Text(${controller.name}));就这么多。所有 Rx 类型RxString、RxInt、RxList、RxMap、RxSet等都基于 rx_interface.dart 中定义的RxInterfaceT契约实现它实现了 Flutter 的ValueListenableT因此可以无缝融入 Flutter 的监听机制。更多细节深入的状态管理讲解简单管理器与响应式管理器的区别、更多示例见 documentation/zh_CN/state_management.md。仓库的 example/lib 演示了使用 GetBuilder/Obx 组织页面数据的完整分层controllers、views、bindings。路由管理GetX 支持免 context 使用路由、snackbars、dialogs、bottomsheets。同样先替换为GetMaterialAppGetMaterialApp( // Before: MaterialApp( home: MyHome(), )常用导航 API// 导航到新页面 Get.to(NextScreen()); // 用别名导航到新页面命名路由详见 documentation/zh_CN/route_management.md Get.toNamed(/details); // 关闭 snackbars, dialogs, bottomsheets 或任何通常用 Navigator.pop(context) 关闭的东西 Get.back(); // 进入下一个页面但没有返回上一页的选项用于闪屏页、登录页等 Get.off(NextScreen()); // 进入下一个页面并取消之前的所有路由购物车、投票、测试中很有用 Get.offAll(NextScreen());核心优势在于所有导航都不需要 context可以在 Controller 中直接调用这些方法。路由系统的底层实现在 lib/get_navigation/src/routes包括GetPage、GetRouterDelegate、GetInformationParser等更完整的别名路由与低级路由控制见 documentation/zh_CN/route_management.md。完整的多模块路由示例含中间件鉴权、抽屉布局见 example_nav2/lib/app。依赖管理Get 的依赖管理器允许用 1 行代码检索到与 Bloc 或 Controller 相同的类无需 Provider context、无需 InheritedWidgetController controller Get.put(Controller()); // 而不是 Controller controller Controller();注意如果使用 Get 的状态管理器请多关注 Bindings API它能让界面更容易连接到控制器。实例在 Get 实例中创建而非使用类中因此整个 App 可用controller.fetchApi();在浏览无数条路由后需要拿回被遗留的控制器数据时Controller controller Get.find(); // 是的它看起来像魔术Get会找到你的控制器并将其提供给你。你可以实例化100万个控制器Get总会给你正确的控制器。随后即可恢复数据Text(controller.textFromApi);依赖管理模块在 lib/get_instance 中实现提供Get.put、Get.find、Get.lazyPut、Get.delete等 API。更多细节见 documentation/zh_CN/dependency_management.md。示例工程中的 Bindings如 home_binding.dart展示了如何把依赖注入与路由页面绑定。实用工具国际化翻译被保存为简单的键值字典映射。要添加自定义翻译创建一个类并继承Translations基类定义见 internationalization.dart其keys为MapString, MapString, Stringimport package:get/get.dart; class Messages extends Translations { override MapString, MapString, String get keys { zh_CN: { hello: 你好 世界, }, de_DE: { hello: Hallo Welt, } }; }使用翻译将.tr追加到指定的键上会使用Get.locale和Get.fallbackLocale的当前值进行翻译Text(title.tr);定义语言向GetMaterialApp传递参数return GetMaterialApp( translations: Messages(), // 你的翻译 locale: Locale(zh, CN), // 将会按照此处指定的语言翻译 fallbackLocale: Locale(en, US), // 回调语言选项以备上面指定的语言翻译不存在 );改变语言调用Get.updateLocale(locale)翻译会自动使用新的 localevar locale Locale(en, US); Get.updateLocale(locale);系统语言读取系统语言可使用window.localeimport dart:ui as ui; return GetMaterialApp( locale: ui.window.locale, );仓库还维护了 12 个语言的完整文档与 README 翻译见 documentation 目录可对照参考各语言的表述。实际的翻译服务示例见 translation_service.dart。改变主题不要使用比GetMaterialApp更高级别的 Widget 来更新主题否则可能造成键重复。无需创建ThemeProviderGet.changeTheme(ThemeData.light());结合「是否深色」的判断 API 与主题更改 API可实现在onPressed中一键切换Get.changeTheme(Get.isDarkMode? ThemeData.light(): ThemeData.dark());当 darkmode 激活时切换到 light 主题light 主题激活时切换到 dark 主题。GetConnectGetConnect可通过 http 或 websockets 便捷地进行前后台通信实现在 lib/get_connect。默认配置通过 extendGetConnect即可使用 GET/POST/PUT/DELETE/SOCKET 方法与 Rest API 或 websockets 通信class UserProvider extends GetConnect { // Get request FutureResponse getUser(int id) get(http://yourapi/users/$id); // Post request FutureResponse postUser(Map data) post(http://yourapi/users, body: data); // Post request with File FutureResponseCasesModel postCases(Listint image) { final form FormData({ file: MultipartFile(image, filename: avatar.png), otherFile: MultipartFile(image, filename: cover.png), }); return post(http://yourapi/users/upload, form); } GetSocket userMessages() { return socket(https://yourapi/users/socket); } }自定义配置GetConnect支持配置 baseUrl、响应与请求修饰、权限认证、认证重试次数以及定义一个标准解码器把响应统一转为模型class HomeProvider extends GetConnect { override void onInit() { // All request will pass to jsonEncode so CasesModel.fromJson() httpClient.defaultDecoder CasesModel.fromJson; httpClient.baseUrl https://api.covid19api.com; // baseUrl https://api.covid19api.com; // It define baseUrl to // Http and websockets if used with no [httpClient] instance // Its will attach apikey property on header from all requests httpClient.addRequestModifier((request) { request.headers[apikey] 12345678; return request; }); // Even if the server sends data from the country Brazil, // it will never be displayed to users, because you remove // that data from the response, even before the response is delivered httpClient.addResponseModifierCasesModel((request, response) { CasesModel model response.body; if (model.countries.contains(Brazil)) { model.countries.remove(Brazilll); } }); httpClient.addAuthenticator((request) async { final response await get(http://yourapi/token); final token response.body[token]; // Set the header request.headers[Authorization] $token; return request; }); //Autenticator will be called 3 times if HttpStatus is //HttpStatus.unauthorized httpClient.maxAuthRetries 3; } override FutureResponseCasesModel getCases(String path) get(path); }注意FormData、MultipartFile等实现位于 lib/get_connect/http/src/multipart请求修饰、认证等拦截器逻辑位于 lib/get_connect/http/src/interceptors。实际可运行的 Provider/Repository 分层示例见 home_api_provider.dart 与 home_repository.dart。GetPage 中间件GetPage有一个新参数可将列表中的 Get 中间件按指定顺序执行。注意当 GetPage 有中间件时所有子 page 会自动继承相同的中间件。中间件的执行顺序在源码 route_middleware.dart 中定义redirect - onPageCalled - onBindingsStart - onPageBuildStart - onPageBuilt - onPageDispose。优先级设置中间件的priority定义执行顺序final middlewares [ GetMiddleware(priority: 2), GetMiddleware(priority: 5), GetMiddleware(priority: 4), GetMiddleware(priority: -8), ];按-8 2 4 5的顺序执行。底层由MiddlewareRunner对中间件列表按priority升序排序后依次调用见 route_middleware.dart。Redirect当被调用路由的页面被搜索时调用。它将RouteSettings作为重定向的结果返回null则不重定向RouteSettings redirect(String route) { final authService Get.findAuthService(); return authService.authed.value ? null : RouteSettings(name: /login) }onPageCalled在调用页面、创建任何东西之前调用可用于更改页面内容或给它一个新页面GetPage onPageCalled(GetPage page) { final authService Get.findAuthService(); return page.copyWith(title: Welcome ${authService.UserName}); }onBindingsStart在绑定初始化之前调用可以在此更改页面的绑定ListBindings onBindingsStart(ListBindings bindings) { final authService Get.findAuthService(); if (authService.isAdmin) { bindings.add(AdminBinding()); } return bindings; }onPageBuildStart在绑定初始化之后、创建页面 Widget 之前调用GetPageBuilder onPageBuildStart(GetPageBuilder page) { print(bindings are ready); return page; }onPageBuilt在GetPage.page被调用后触发接收函数结果并拿到将要显示的 Widget。onPageDispose在处理完页面的所有相关对象Controllers、views 等之后调用。一个实际使用中间件做登录鉴权的示例见 auth_middleware.dart它配合 app_pages.dart 中的GetPage(middlewares: [...])工作。其他高级 API// 给出当前页面的args。 Get.arguments //给出以前的路由名称 Get.previousRoute // 给出要访问的原始路由例如rawRoute.isFirst() Get.rawRoute // 允许从GetObserver访问Rounting API。 Get.routing // 检查 snackbar 是否打开 Get.isSnackbarOpen // 检查 dialog 是否打开 Get.isDialogOpen // 检查 bottomsheet 是否打开 Get.isBottomSheetOpen // 删除一个路由。 Get.removeRoute() //反复返回直到表达式返回真。 Get.until() // 转到下一条路由并删除所有之前的路由直到表达式返回true。 Get.offUntil() // 转到下一个命名的路由并删除所有之前的路由直到表达式返回true。 Get.offNamedUntil() //检查应用程序在哪个平台上运行。 GetPlatform.isAndroid GetPlatform.isIOS GetPlatform.isMacOS GetPlatform.isWindows GetPlatform.isLinux GetPlatform.isFuchsia //检查设备类型 GetPlatform.isMobile GetPlatform.isDesktop //所有平台都是独立支持web的! //你可以知道你是否在浏览器内运行。 //在Windows、iOS、OSX、Android等系统上。 GetPlatform.isWeb // 相当于.MediaQuery.of(context).size.height, 但不可改变。 Get.height Get.width // 提供当前上下文。 Get.context // 在你的代码中的任何地方在前台提供 snackbar/dialog/bottomsheet 的上下文。 Get.contextOverlay以下方法是对BuildContext的扩展可在 UI 代码的任何地方使用// 可改变的高度/宽度桌面或浏览器窗口可缩放时使用 context.width context.height // 让您可以定义一半的页面、三分之一的页面等对响应式应用很有用。 // 参数 dividedBy (double) 可选 - 默认值1 // 参数 reducedBy (double) 可选 - 默认值0 context.heightTransformer() context.widthTransformer() // 类似于 MediaQuery.of(context).size。 context.mediaQuerySize() // 类似于 MediaQuery.of(context).padding。 context.mediaQueryPadding() // 类似于 MediaQuery.of(context).viewPadding。 context.mediaQueryViewPadding() // 类似于 MediaQuery.of(context).viewInsets。 context.mediaQueryViewInsets() // 类似于 MediaQuery.of(context).orientation。 context.orientation() // 检查设备是否处于横向模式 context.isLandscape() // 检查设备是否处于纵向模式。 context.isPortrait() // 类似于MediaQuery.of(context).devicePixelRatio。 context.devicePixelRatio() // 类似于MediaQuery.of(context).textScaleFactor。 context.textScaleFactor() // 查询设备最短边。 context.mediaQueryShortestSide() // 如果宽度大于800则为真。 context.showNavbar() // 如果最短边小于600p则为真。 context.isPhone() // 如果最短边大于600p则为真。 context.isSmallTablet() // 如果最短边大于720p则为真。 context.isLargeTablet() // 如果当前设备是平板电脑则为真 context.isTablet() // 根据页面大小返回一个值T。 // 可以给值为 // watch如果最短边小于300 // mobile如果最短边小于600 // tablet如果最短边shortestSide小于1200 // desktop如果宽度大于1200 context.responsiveValueT()尺寸与响应式扩展的实现见 context_extensions.dart平台判断见 platform.dart。可选的全局设置和手动配置GetMaterialApp为你配置了一切但也可以手动配置MaterialApp( navigatorKey: Get.key, navigatorObservers: [GetObserver()], );也可以在GetObserver中使用自己的中间件MaterialApp( navigatorKey: Get.key, navigatorObservers: [ GetObserver(MiddleWare.observer) // Here ], );为 Get 创建全局设置只需在推送任何路由之前调用Get.config或在GetMaterialApp中配置GetMaterialApp( enableLog: true, defaultTransition: Transition.fade, opaqueRoute: Get.isOpaqueRouteDefault, popGesture: Get.isPopGestureEnable, transitionDuration: Get.defaultDurationTransition, defaultGlobalState: Get.defaultGlobalState, ); Get.config( enableLog true, defaultPopGesture true, defaultTransition Transitions.cupertino )还可以重定向所有来自 Get 的日志信息接入自己喜爱的日志包GetMaterialApp( enableLog: true, logWriterCallback: localLogWriter, ); void localLogWriter(String text, {bool isError false}) { // 在这里把信息传递给你最喜欢的日志包。 // 请注意即使enableLog: false日志信息也会在这个回调中被推送。 // 如果你想的话可以通过GetConfig.isLogEnable来检查这个标志。 }日志机制的基础实现在 log.dartSmartManagement与全局状态开关定义于 get_interface.dart 与 smart_management.dart。局部状态组件这些 Widget 允许你管理单一的值并保持状态的短暂性和局部性有 Reactive 和 Simple 两种风格。例如切换TextField的 obscureText、创建自定义可扩展面板、在修改BottomNavigationBar索引的同时改变Scaffold主体内容。ValueBuilderStatefulWidget的简化与.setState回调配合并接受更新后的值ValueBuilderbool( initialValue: false, builder: (value, updateFn) Switch( value: value, onChanged: updateFn, // 你可以用( newValue ) updateFn( newValue ) ), // 如果你需要调用 builder 方法之外的东西。 onUpdate: (value) print(Value updated: $value), onDispose: () print(Widget unmounted), ),ObxValue与ValueBuilder类似但这是响应式版本需要传入一个 Rx 实例ObxValue((data) Switch( value: data.value, onChanged: data, // Rx 有一个 _callable_ 函数! 你可以使用 (flag) data.value flag ), false.obs, ),有用的提示.obs可观察对象也称 Rx Types有各种内部方法和操作符。.obs的属性是实际值不要搞错 我们避免声明变量类型因为 Dart 编译器足够聪明且代码更干净但var message Hello world.obs; print( Message $message has Type ${message.runtimeType});即使messageprints实际的字符串值其类型也是RxString所以不能直接message.substring(0, 4)必须在 observable 内部访问真正的value。最常用的是.value但还有更多玩法final name GetX.obs; // 只有在值与当前值不同的情况下才会 更新 流。 name.value Hey; // 所有Rx属性都是 可调用 的并返回新的值。 // 但这种方法不接受 nullUI将不会重建。 name(Hello); // 就像一个getter打印Hello。 name(); ///数字。 final count 0.obs; // 您可以使用num基元的所有不可变操作! count 1; // 注意只有当 count 不是final时这才有效除了var count 1; // 你也可以与数值进行比较。 count 2; /// booleans: final flag false.obs; // 在真/假之间切换数值 flag.toggle(); /// 所有类型。 // 将 value 设为空。 flag.nil(); // 所有的toString()、toJson()操作都会向下传递到value。 print( count ); // 在内部调用 toString() 来 GetRxInt final abc [0,1,2].obs; // 将值转换为json数组打印RxList。 // 所有Rx类型都支持Json! print(json: ${jsonEncode(abc)}, type: ${abc.runtimeType}); // RxMap, RxList 和 RxSet 是特殊的 Rx 类型扩展了它们的原生类型。 // 但你可以像使用普通列表一样使用列表尽管它是响应式的。 abc.add(12); // 将12添加到列表中并更新流。 abc[3]; // 和Lists一样读取索引3。 // Rx和值是平等的但hashCode总是从值中提取。 final number 12.obs; print( number 12 ); // prints true ///自定义Rx模型。 // toJson(), toString()都是递延给子代的所以你可以在它们上实现覆盖并直接print()可观察的内容。 class User { String name, last; int age; User({this.name, this.last, this.age}); override String toString() $name $last, $age years old; } final user User(name: John, last: Doe, age: 33).obs; // user是 响应式 的但里面的属性却不是! // 所以如果我们改变其中的一些变量 user.value.name Roi; // 小部件不会重建 // 对于自定义类我们需要手动 通知 改变。 user.refresh(); // 或者我们可以使用update()方法! user.update((value){ value.nameRoi; }); print( user );GetViewGetView是一个对已注册 Controller 提供名为controller的 getter 的const StatelessWidget实现见 get_view.dartclass AwesomeController extends GetxController { final String title My Awesome View; } // 一定要记住传递你用来注册控制器的Type! class AwesomeView extends GetViewAwesomeController { override Widget build(BuildContext context) { return Container( padding: EdgeInsets.all(20), child: Text( controller.title ), // 只需调用 controller.something ); } }GetWidgetGetWidget的用例非常少见且特殊它「缓存」了一个 Controller由于缓存的存在不能成为const Stateless。什么时候需要缓存一个 Controller如果你使用了Get.create()Get.create(()Controller())会在每次调用Get.findController()时生成一个新的 Controller。使用GetWidget可以保存 Todo 项目列表即使 Widget 被「重建」也会保持相同的控制器实例。GetxServiceGetxService与GetxController共享相同生命周期onInit()、onReady()、onClose()但内部没有「逻辑」它只是通知 GetX 的依赖注入系统这个子类不能从内存中删除。所以它对于保持ApiService、StorageService、CacheService等服务始终可被Get.find()获取并保持运行非常有用Futurevoid main() async { await initServices(); /// 等待服务初始化. runApp(SomeApp()); } /// 在运行Flutter应用之前让服务初始化是明智之举 /// 因为你可以控制执行流程也许你需要加载一些主题配置、apiKey、用户自定义的语言等 /// 所以在运行ApiService之前加载SettingService。 void initServices() async { print(starting services ...); ///这里是你放get_storage、hive、shared_pref初始化的地方。 ///或者moor连接或者其他什么异步的东西。 await Get.putAsync(() DbService().init()); await Get.putAsync(SettingsService()).init(); print(All services started...); } class DbService extends GetxService { FutureDbService init() async { print($runtimeType delays 2 sec); await 2.delay(); print($runtimeType ready!); return this; } } class SettingsService extends GetxService { void init() async { print($runtimeType delays 1 sec); await 1.delay(); print($runtimeType ready!); } }实际删除一个GetxService的唯一方法是使用Get.reset()它就像「热重启」你的应用。如果需要在应用生命周期内对类实例绝对持久化请使用GetxService。从 2.0 开始的兼容性变化1. Rx 类型改名BeforeAfterStringXRxStringIntXRxIntMapXRxMapListXRxListNumXRxNumDoubleXRxDouble现在RxController和GetBuilder已合并你不再需要记住用哪个控制器只要用GetxController即可它同时支持简单状态管理与响应式。2. 别名路由之前GetMaterialApp( namedRoutes: { /: GetRoute(page: Home()), } )现在GetMaterialApp( getPages: [ GetPage(name: /, page: () Home()), ] )为什么这样改通常可能需要通过一个参数或登录令牌来决定显示哪个页面。将页面插入函数中大大降低了 RAM 消耗——应用启动后路由不会在内存中分配GetStorage box GetStorage(); GetMaterialApp( getPages: [ GetPage(name: /, page:(){ return box.hasData(token) ? Home() : Login(); }) ] )为什么选择 GetX依赖集中、兼容统一Flutter 更新常导致多个包损坏。Get 将开发的主要资源状态、依赖和路由管理集中在同一个包中Flutter 更新后只需更新 Get 依赖即可继续工作且不存在多包版本互相不兼容的问题。极简 API如Get.to(Home())一行完成导航.obsObx完成状态响应动态网页 URL 处理也非常简单。自动内存管理SmartManagement所有不被使用的控制器会从内存中自动删除保证只消耗最低限度的必要资源。实际解耦控制器拥有独立生命周期如onInit启动 http 调用、数据到达后填充变量UI 人员只需处理 Widget 与用户事件业务逻辑人员可以自由地单独创建和测试业务逻辑。总结GetX 以「状态管理 依赖注入 路由管理」三位一体的方式解决了 Flutter 开发中的高频痛点并通过 GetMaterialApp、GetConnect、GetPage 中间件、国际化、主题切换与丰富的上下文扩展工具提供了完整的应用开发闭环。从本仓库的 example 与 example_nav2 两个示例工程可以看到从简单计数器到多模块、带鉴权中间件的完整应用结构而 documentation 目录下各语言的专项文档state_management.md、route_management.md、dependency_management.md可作为深入学习的下一站。赞分享前端【免费下载链接】getxOpen screens/snackbars/dialogs/bottomSheets without context, manage states and inject dependencies easily with Get.项目地址https://gitcode.com/gh_mirrors/ge/getx点击查看免费下载相关推荐flutter-examples中的GetX路由、状态与依赖管理一体化flutter examples中的GetX路由、状态与依赖管理一体化 你是否还在为Flutter应用中的状态管理、路由跳转和依赖注入编写大量样板代码是否在示例工程移动开发AGEIPort最佳实践避免常见陷阱的10个实用技巧AGEIPort最佳实践避免常见陷阱的10个实用技巧 AGEIPort是阿里巴巴开源的高性能数据导入导出框架专门为复杂toB业务场景设计能够帮助开发者快速前端深度性能评估PTO-ISA在Ascend AI处理器上的Dhrystone基准测试分析深度性能评估PTO ISA在Ascend AI处理器上的Dhrystone基准测试分析 PTO ISA Parallel Tile Operation虚拟指前端上一篇Sandboxie异常检测机制识别可疑应用行为模式下一篇EMQX消息积压处理队列机制与流量控制创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考