Flutter 3.19 发布,快来看看有什么更新吧?

参考链接:https://medium.com/flutter/whats-new-in-flutter-3-19-58b1aae242d2

新年假期的尾巴,Flutter 迎来了 3.19 更新,该版本带来了 Gemini(Google’s most capable AI ) 的 Dart SDK,更好控制动画颗粒度的 Widget ,Impeller 的性能增强和 Android 优化支持,deep links 工具支持,Android 和 iOS 上的特定平台新支持,Windows Arm64 支持等等。

普遍优化修复居多。

Gemini Dart SDK

Google 的 AI Dart SDK Gemini 目前已经发布,pub 上的 google_generative_ai 将 Gemini 的生成式 AI 功能支持到 Dart 或 Flutter 应用里,Google Generative AI SDK 可以更方便地让 Dart 开发人员在 App 里集成 LLM 的 AI 能力。

import 'dart:io';

import 'package:google_generative_ai/google_generative_ai.dart';

void main() async {
  // Access your API key as an environment variable (see first step above)
  final apiKey = Platform.environment['API_KEY'];
  if (apiKey == null) {
    print('No \$API_KEY environment variable');
    exit(1);
  }
  // For text-and-image input (multimodal), use the gemini-pro-vision model
  final model = GenerativeModel(model: 'gemini-pro-vision', apiKey: apiKey);
  final (firstImage, secondImage) = await (
    File('image0.jpg').readAsBytes(),
    File('image1.jpg').readAsBytes()
  ).wait;
  final prompt = TextPart("What's different between these pictures?");
  final imageParts = [
    DataPart('image/jpeg', firstImage),
    DataPart('image/jpeg', secondImage),
  ];
  final response = await model.generateContent([
    Content.multi([prompt, ...imageParts])
  ]);
  print(response.text);
}

Framework

滚动优化

在 3.19 之前,使用两根手指在 Flutter 列表上进行滑动时,Flutter 的滚动速度会加快到两倍,这一直是一个饱受争议的问题,现在,从 3.19 开始,开发者可以使用 MultiTouchDragStrategy.latestPointer 来配置默认的 ScrollBehavior ,从而让滑动效果与手指数量无关。

ScrollBehavior.multitouchDragStrategy 默认情况下会防止多个手指同时与可滚动对象进行交互,从而影响滚动速度,如果之前你已经依赖老板本这个多指滑动能力,那么可以通过 MaterialApp.scrollBehavior / CupertinoApp.scrollBehavior 去恢复:

class MyCustomScrollBehavior extends MaterialScrollBehavior {
  // Override behavior methods and getters like multitouchDragStrategy
  
  MultitouchDragStrategy get multitouchDragStrategy => MultitouchDragStrategy.sumAllPointers;
}

// Set ScrollBehavior for an entire application.
MaterialApp(
  scrollBehavior: MyCustomScrollBehavior(),
  // ...
);

或者通过 ScrollConfiguration 进行局部配置:

class MyCustomScrollBehavior extends MaterialScrollBehavior {
  // Override behavior methods and getters like multitouchDragStrategy
  
  MultitouchDragStrategy get multitouchDragStrategy => MultitouchDragStrategy.sumAllPointers;
}

// ScrollBehavior can be set for a specific widget.
final ScrollController controller = ScrollController();
ScrollConfiguration(
  behavior: MyCustomScrollBehavior(),
  child: ListView.builder(
    controller: controller,
    itemBuilder: (BuildContext context, int index) {
      return Text('Item $index');
    },
  ),
);

详细可参考:https://docs.flutter.dev/release/breaking-changes/multi-touch-scrolling

另外,本次 3.19 还修复了 SingleChildScrollView#136871 和 ReorderableList#136828 相关的崩溃问题,同时 two_dimensional_scrollables 也修复了一些问题,比如在任一方向上正在进行滚动时出现拖动或者点击,scroll activity 将按预期停止。

最后,two_dimensional_scrollables 上的 TableView 控件也进行了多次更新,提供了需要改进,例如添加了对合并单元格的支持,并在上一个稳定版本 3.16 之后适配了更多 2D foundation。

AnimationStyle

来自社区 @TahaTesser 的贡献,现在 Flutter 开发者使用 AnimationStyle ,可以让用户快速覆盖 Widget 中的默认动画行为,就像 MaterialAppExpansionTilePopupMenuButton

   popUpAnimationStyle: AnimationStyle(
            curve: Easing.emphasizedAccelerate,
            duration: Durations.medium4,
          ),
return MaterialApp(
      themeAnimationStyle: AnimationStyle.noAnimation,

SegmentedButton.styleFrom

来自社区成员 @AcarFurkan 的贡献,该静态方式就像其他按钮类型提供的方法一样。可以快速创建分段按钮的按钮样式,可以与其他分段按钮共享或用于配置应用的分段按钮主题。

Adaptive Switch

Adaptive Switch 可以让 Widget 在 macOS 和 iOS 上看起来和感觉是原生的效果,并且在其他地方具有 Material Design 的外观和感觉,它不依赖于 Cupertino 库,因此它的 API 在所有平台上都完全相同。

import 'package:flutter/material.dart';

/// Flutter code sample for [Switch.adaptive].

void main() => runApp(const SwitchApp());

class SwitchApp extends StatefulWidget {
  const SwitchApp({super.key});

  
  State<SwitchApp> createState() => _SwitchAppState();
}

class _SwitchAppState extends State<SwitchApp> {
  bool isMaterial = true;
  bool isCustomized = false;

  
  Widget build(BuildContext context) {
    final ThemeData theme = ThemeData(
        platform: isMaterial ? TargetPlatform.android : TargetPlatform.iOS,
        adaptations: <Adaptation<Object>>[
          if (isCustomized) const _SwitchThemeAdaptation()
        ]);
    final ButtonStyle style = OutlinedButton.styleFrom(
      fixedSize: const Size(220, 40),
    );

    return MaterialApp(
      theme: theme,
      home: Scaffold(
        appBar: AppBar(title: const Text('Adaptive Switches')),
        body: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            OutlinedButton(
              style: style,
              onPressed: () {
                setState(() {
                  isMaterial = !isMaterial;
                });
              },
              child: isMaterial
                  ? const Text('Show cupertino style')
                  : const Text('Show material style'),
            ),
            OutlinedButton(
              style: style,
              onPressed: () {
                setState(() {
                  isCustomized = !isCustomized;
                });
              },
              child: isCustomized
                  ? const Text('Remove customization')
                  : const Text('Add customization'),
            ),
            const SizedBox(height: 20),
            const SwitchWithLabel(label: 'enabled', enabled: true),
            const SwitchWithLabel(label: 'disabled', enabled: false),
          ],
        ),
      ),
    );
  }
}

class SwitchWithLabel extends StatefulWidget {
  const SwitchWithLabel({
    super.key,
    required this.enabled,
    required this.label,
  });

  final bool enabled;
  final String label;

  
  State<SwitchWithLabel> createState() => _SwitchWithLabelState();
}

class _SwitchWithLabelState extends State<SwitchWithLabel> {
  bool active = true;

  
  Widget build(BuildContext context) {
    return Row(
      mainAxisAlignment: MainAxisAlignment.center,
      children: <Widget>[
        Container(
            width: 150,
            padding: const EdgeInsets.only(right: 20),
            child: Text(widget.label)),
        Switch.adaptive(
          value: active,
          onChanged: !widget.enabled
              ? null
              : (bool value) {
                  setState(() {
                    active = value;
                  });
                },
        ),
      ],
    );
  }
}

class _SwitchThemeAdaptation extends Adaptation<SwitchThemeData> {
  const _SwitchThemeAdaptation();

  
  SwitchThemeData adapt(ThemeData theme, SwitchThemeData defaultValue) {
    switch (theme.platform) {
      case TargetPlatform.android:
      case TargetPlatform.fuchsia:
      case TargetPlatform.linux:
      case TargetPlatform.windows:
        return defaultValue;
      case TargetPlatform.iOS:
      case TargetPlatform.macOS:
        return SwitchThemeData(
          thumbColor: MaterialStateProperty.resolveWith<Color?>(
              (Set<MaterialState> states) {
            if (states.contains(MaterialState.selected)) {
              return Colors.yellow;
            }
            return null; // Use the default.
          }),
          trackColor: const MaterialStatePropertyAll<Color>(Colors.brown),
        );
    }
  }
}

详细可见:https://main-api.flutter.dev/flutter/material/Switch/Switch.adaptive.html

SemanticsProperties 可访问性标识符

3.19 里SemanticsProperties 添加了新的可访问性标识符,为 native 可访问性层次结构中的语义节点提供标识符。

  • 在 Android 上,它在辅助功能层次结构中显示为 “resource-id”

  • 在 iOS 上是设置里 UIAccessibilityElement.accessibilityIdentifier

MaterialStatesController

TextFieldTextFormField 添加了 MaterialStatesController ,因为在此之前,开发者无法确定 TextFormField 当前是否处于错误状态,例如:

  • 它显示错误消息并使用了errorBorder
  • 确定它是否 foucs,但前提是提供自己的 FocusNode

而现在允许开发者提供自己的 MaterialStatesController(类似于ElevatedButton),以便开发者可以完全访问有关这些控件的状态信息。

final MaterialStatesController statesController = MaterialStatesController();
statesController.addListener(valueChanged);

TextField(
  statesController: statesController,
  controller: textEditingController,
)

UndoHistory stack

修复了 undo/redo 历史在日语键盘上可能消失的问题,并使其现在可以在将条目推送到 UndoHistory 堆栈之前对其进行修改。

UndoHistory 是一个提供撤消/重做功能的 Widget,它还具有绑定到特定于平台的实现的底层接口,监听了键盘事件以实现 undo/redo 操作。

从 Flutter 3.0.0 开始,可以将 UndoHistoryController 传递给 TextField它附带了 UndoHistoryValue

对于一个非常简单的展示,我将创建一个 UndoHistoryController 实例,将其传递给 TextField,使用 ValueListenableBuilder 监听该实例,并在构建器中的按钮上返回一行以执行撤消/重做操作。

import 'package:flutter/material.dart';

/// Flutter code sample for [UndoHistoryController].

void main() {
  runApp(const UndoHistoryControllerExampleApp());
}

class UndoHistoryControllerExampleApp extends StatelessWidget {
  const UndoHistoryControllerExampleApp({super.key});

  
  Widget build(BuildContext context) {
    return const MaterialApp(
      home: MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({super.key});

  
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  final TextEditingController _controller = TextEditingController();
  final FocusNode _focusNode = FocusNode();
  final UndoHistoryController _undoController = UndoHistoryController();

  TextStyle? get enabledStyle => Theme.of(context).textTheme.bodyMedium;
  TextStyle? get disabledStyle =>
      Theme.of(context).textTheme.bodyMedium?.copyWith(color: Colors.grey);

  
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            TextField(
              maxLines: 4,
              controller: _controller,
              focusNode: _focusNode,
              undoController: _undoController,
            ),
            ValueListenableBuilder<UndoHistoryValue>(
              valueListenable: _undoController,
              builder: (BuildContext context, UndoHistoryValue value,
                  Widget? child) {
                return Row(
                  children: <Widget>[
                    TextButton(
                      child: Text('Undo',
                          style: value.canUndo ? enabledStyle : disabledStyle),
                      onPressed: () {
                        _undoController.undo();
                      },
                    ),
                    TextButton(
                      child: Text('Redo',
                          style: value.canRedo ? enabledStyle : disabledStyle),
                      onPressed: () {
                        _undoController.redo();
                      },
                    ),
                  ],
                );
              },
            ),
          ],
        ),
      ),
    );
  }
}

Engine

Impeller 进度

Android OpenGL 预览

在 3.16 稳定版本中,Flutter 官方邀请了用户在支持 Vulkan 的 Android 设备上试用 Impeller,覆盖了该领域 77% 的 Android 设备,而在过去的几个月里,Flutter 官方团队让 Impeller 的 OpenGL 达到了与 Vulkan 同等的功能,例如添加支持 MSAA。

这意味着几乎所有 Android 设备上的 Flutter 应用都有望支持 Impeller 渲染,除了少数即将推出的剩余功能除外,例如自定义着色器和对外部纹理的完全支持,目前官方团队表示在今年晚些时候 Androd 也会将 Impeller 作为默认渲染器。

另外,Impeller 的 Vulkan 在“调试”构建中启用了超出 Skia 的附加调试功能,并且这些功能会产生额外的运行时开销。因此,有关 Impeller 性能的反馈你许来自 profile 或 release 版本,并且需要包括 DevTools 的时间表以及与同一设备上的 Skia 后端的比较。

路线

在实现了渲染保真度之后,在 Impeller Android 预览期间的主要关注点是性能,另外一些更大的改进也正在进行,例如能够利用 Vulkan subpasses 大大提高高级混合模式的性能。

此外,Flutter 官方还期望渲染策略发生变化,不再总是将 CPU 上的每条路径细分为先模板后覆盖 ,这样的实现将大大降低 Android 和 iOS 上 Impeller 的 CPU 利用率。

最后,Flutter 还期望新的高斯模糊实施能匹配 Skia 实现的吞吐量,并改进 iOS 上模糊的惯用用法。

API 改进

字形信息

3.19 版本包括两个新的 dart:ui 方法:Paragraph getClosestGlyphInfoForOffsetgetGlyphInfoAt,这两个方式都会返回一个新类型的对象字形信息,包含段落内字符(或视觉上相连的字符序列)的尺寸。

  • Paragraph.getGlyphInfoAt,查找与文本中的代码单元关联的 GlyphInfo
  • Paragraph.getClosestGlyphInfoForOffset,查找屏幕上最接近给定 Offset 的字形的 GlyphInfo

GPU追踪

Metal 下的 Impeller(iOS、macOS、模拟器) 和在支持 Vulkan 的 Android 设备上,Flutter 引擎现在将在调试和 profile 构建中报告时间线中每个帧的 GPU 时间,可以在 DevTools 中的 “GPUTracer” 下检查 GPU 帧时序。

请注意,由于非 Vulkan Android 设备可能会误报其对查询 GPU 计时的支持,因此只能通过在 AndroidManifest.xml 设置标志来启用 Impeller 的 GPU 跟踪:

<meta-data
    android:name="io.flutter.embedding.android.EnableOpenGLGPUTracing"
    android:value="true" /> 

性能优化

Specialization Constants

Impeller 添加支持 Specialization Constants ,利用 Impeller 着色器中的这一功能,减少了 Flutter 引擎的未压缩二进制大小 350KB。

Backdrop Filter 加速

3.19 版本包含一些不错的性能改进,其中就包括了 Impeller 的 Backdrop Filter 和模糊优化,特别是开源贡献者 knopp noticed 注意到 Impeller 错误地请求了读取屏幕纹理的功能,删除这个功能支持,在基准测试中,根据复杂程度,将包含多个背景滤镜的场景改进了 20-70%。

同时,Impeller 在每个背景滤镜上不再无条件存储模板缓冲区,相反,任何影响操作的剪辑都会被记录下来,并在恢复背景滤镜的保存层时重播到新的模板缓冲区中。

通过这一更改,在运行具有 Vulkan 的 Impeller 的 Pixel 7 Pro 上进行动画高级混合模式基准测试时,将平均 GPU 帧时间从 55 毫秒改进到 16 毫秒,并将 90% 的光栅线程 CPU 时间从大约 110 毫秒改进到 22 毫秒。

Android

Deeplinking web 验证器

3.19 开始,Flutter 的 Deeplinking web 验证器的早期版本将被推出使用。

在该版本中,Flutter Deeplinking 验证器支持 Android 上的 Web 检查,这意味着可以验证 assetlinks.json 文件的设置。

开发者可以打开DevTools,单击 “Deep Links” 选项,然后导入包含 Deeplinking 的 Flutter 项目,Deeplinking 验证器将告诉你配置是否正确。

Flutter 希望这个工具能够成为简化的 Deeplinking ,后续将继续补全 iOS 上的 Web 检查以及 iOS 和 Android 上的应用检查的支持。

更多可以查阅 :https://docs.google.com/document/d/1fnWe8EpZleMtSmP0rFm2iulqS3-gA86z8u9IsnXjJak/edit

支持 Share.invoke

Android 平台上 Flutter 之前缺少默认 “share” 按钮,而本次 3.19 里将开始支持它,作为 Flutter 持续努力的一部分,以确保所有默认上下文菜单按钮在每个平台上都可用。

更多相关进度可见:https://github.com/flutter/flutter/issues/107578

Native assets

如果需要 Flutter 代码中与其他语言的其他函数进行互操作,现在可以在 Android 上通过执行 FFI 来处理 Native assets 。

简单来说就是,在此之前, Dart interop 一直在全面支持与 Java 和 Kotlin 和 Objective C 和 Swift 的直接调用支持,例如在 Dart 3.2 开始,Native assets 就作为实验性测试支持,一直在解决与依赖于 Native 代码的 Dart 包分发相关的许多问题,它通过提供统一的钩子来与构建 Flutter 和独立 Dart 应用所涉及的各种构建需要。

Native Assets 可以让 Dart 包更无缝依赖和使用 Native 代码,通过 flutter run/flutter build dart run/dart build 构建并捆绑 Native 代码 。

备注:可通过 flutter config --enable-native-assetsflutter create --template=package_ffi [package name] 启用。

Demo native_add_library 就展示了相关使用,当 Flutter 项目依赖 package:native_add_library 时, 脚本会自动在 build.dart 命令上调用:

import 'package:native_add_library/native_add_library.dart';

void main() {
  print('Invoking a native function to calculate 1 + 2.');
  final result = add(1, 2);
  print('Invocation success: 1 + 2 = $result.');
}

更多可见:https://github.com/flutter/flutter/issues/129757

纹理层混合合成 (THLC) 模式

现在使 Google 地图 SDK 和文本输入框的放大镜功能时,他们都是工作在 TLHC 模式下,这会让 App 的性能得到不错的提升。

自定义 system-wide text selection toolbar 按键

Android 应用可以添加出现在所有文本选择菜单(长按文本时出现的菜单)中的自定义文本选择菜单项, Flutter 的 TextField 选择菜单现在包含了这些项目。

在 Android 上,一般可以编写一个应用,将自定义按钮添加到系统范围的文本选择工具栏上。例如上图这里 Android 应用 AnkiDroid 在文本选择工具栏中添加了 “Anki Card ”按钮,并且它可以出现在任何应用中。

iOS

Flutter iOS 原生字体

Flutter 文本现在在 iOS 上看起来更紧凑、更像 native,因为根据苹果设计指南,iOS 上较小的字体应该更加分散,以便在移动设备上更容易阅读,而较大的字体应该更加紧凑,以免占用太多空间。

在此之前,我们在所有情况下都错误地使用了更小、间距更大的字体,现在默认情况下 Flutter 将为较大的文本使用紧凑字体。

开发工具

开发工具更新

3.19 版本的 DevTools 的一些亮点包括:

● 在 DevTools 中添加了新功能以进行验证 Deeplinking

● 在 “Enhance Tracing” 菜单中添加了一个选项,用于跟踪平台 channel activity,这对于带有插件的应用很有用

● 当没有连接的应用时,性能和 CPU 分析器现在也可以使用,可以重新加载之前从 DevTools 保存的性能数据或 CPU 配置文件

● VS Code 中的 Flutter 侧边栏现在能够在当前项目未启用的情况下启用新平台,并且侧边栏中的 DevTools 菜单现在有一个在外部浏览器窗口中使用 DevTools 的选项

桌面

Windows Arm64 支持

Windows 上的 Flutter 现在开始初步支持 Arm64 架构,目前仍处于开发阶段, 可以在GitHub #62597 上查看进度,虽然目前对于 Flutter 开发者来说可能用处不是特别明显,但是也算是一个难得的桌面增强。

生态系统

隐私清单

Flutter 现在包含 iOS 上的隐私清单以满足即将推出的 Apple 要求 ,所以看来一般情况下,这个 Flutter 3.19 非升不可

包生态的进展

2023 年,pub package 生态增长了 26%,从 1 月份的 38,000 个 package 增加到 12 月底的 48,000 个,截至 2024 年 1 月,Pub.dev 现在每月活跃用户超过 700,000 名,

弃用和重大变更

放弃 Windows 7 和 8 支持

Dart 3.3 和 Flutter 3.19 版本停止对 Windows 7 和 8 的支持

Impeller Dithering flag

正如 3.16 发布时所说的,现在全局标志 Paint.enableDithering 已经删除。

弃用 iOS 11

Flutter 不再支持 iOS 11,由于调用某些网络 API 时会发生运行时崩溃, Flutter 3.16.6 及更高版本构建的应用将不再支持 iOS11 ,详细可见 :https://juejin.cn/post/7321410906427359258。

最后

目前看来 Flutter 3.19 并没有什么大更新,属于季度正常迭代,主要是问题修复和性能高优化的版本,还是老规矩,坐等 3.19.6 版本。

最后,新年快乐~准备开工咯。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

扶贫|精准扶贫管理系统|基于Springboot的精准扶贫管理系统设计与实现(源码+数据库+文档)

精准扶贫管理系统目录 目录 基于Springboot的精准扶贫管理系统设计与实现 一、前言 二、系统功能设计 三、系统实现 1、管理员模块的实现 &#xff08;1&#xff09;用户信息管理 &#xff08;2&#xff09;贫困户信息管理 &#xff08;3&#xff09;新闻类型管理 &a…

【论文精读】GPT2

摘要 在单一领域数据集上训练单一任务的模型是当前系统普遍缺乏泛化能力的主要原因&#xff0c;要想使用当前的架构构建出稳健的系统&#xff0c;可能需要多任务学习。但多任务需要多数据集&#xff0c;而继续扩大数据集和目标设计的规模是个难以处理的问题&#xff0c;所以只能…

【MySQL】:DQL查询

&#x1f3a5; 屿小夏 &#xff1a; 个人主页 &#x1f525;个人专栏 &#xff1a; MySQL从入门到进阶 &#x1f304; 莫道桑榆晚&#xff0c;为霞尚满天&#xff01; 文章目录 &#x1f4d1;前言一. DQL1.1 基本语法1.2 基础查询1.3 条件查询1.3 聚合函数 &#x1f324;️ 全篇…

【AI绘画】硬核解读Stable Diffusion(完整版) 小白必收藏!!!

手把手教你入门绘图超强的AI绘画&#xff0c;用户只需要输入一段图片的文字描述&#xff0c;即可生成精美的绘画。给大家带来了全新保姆级教程资料包 &#xff08;文末可获取&#xff09; 2022年可谓是AIGC&#xff08;AI Generated Content&#xff09;元年&#xff0c;上半年…

【Linux网络编程五】Tcp套接字编程(四个版本服务器编写)

【Linux网络编程五】Tcp套接字编程(四个版本服务器编写&#xff09; [Tcp套接字编程]一.服务器端进程&#xff1a;1.创建套接字2.绑定网络信息3.设置监听状态4.获取新连接5.根据新连接进行通信 二.客户端进程&#xff1a;1.创建套接字2.连接服务器套接字3.连接成功后进行通信 三…

JavaScript中的变量监听:实时捕捉变化的利器

JavaScript中的变量监听&#xff1a;实时捕捉变化的利器 在JavaScript开发中&#xff0c;经常需要监听变量的改变&#xff0c;并在变量值发生变化时执行相应的操作。这种实时捕捉变化的功能对于构建交互性强的应用程序至关重要。本文将介绍如何在JavaScript中监听变量的改变&am…

模型 4C(消费者、成本、编译、沟通)理论

系列文章 分享 模型&#xff0c;了解更多&#x1f449; 模型_总纲目录。重在提升认知。以消费者为中心。 1 4C(消费者、成本、编译、沟通)理论的应用 1.1 4C理论在电子商务中的应用 亚马逊是4C营销战略的成功案例。以下是对亚马逊应用4C理论的详细解读&#xff1a; 消费者&a…

【JavaEE Spring 项目】博客系统

博客系统 前⾔项⽬介绍1. 准备⼯作1.1 数据准备1.2 创建项⽬1.3 准备前端⻚⾯1.4 配置配置⽂件1.5 测试 2. 项⽬公共模块2.1 实体类的编写2.2 公共层 3. 业务代码3.1 持久层3.2 实现博客列表3.3 实现博客详情3.4 实现登陆令牌技术JWT令牌介绍JWT令牌⽣成和校验 3.5 实现强制要求…

Python入门知识点分享——(二十一)多继承和运算符重载

在介绍新的知识之前&#xff0c;我们先对之前的内容做一点补充&#xff0c;在面向对象编程的过程中&#xff0c;一个对象常常被要求具备多方面的功能&#xff0c;从而和多个类产生联系&#xff0c;而这一步的实现就用到了“多继承”。多继承是指一个子类可以继承自多个父类&…

【Linux】Linux编译器-gcc/g++ Linux项目自动化构建工具-make/Makefile

目录 Linux编译器-gcc/g使用 1.背景知识 Linux中头文件的目录在 Linux 库 条件编译的典型应用 2.gcc如何完成 动态库 vs 静态库 debug && release Linux项目自动化构建工具-make/Makefile 背景 用法 特殊符号 Linux编译器-gcc/g使用 1.背景知识 预处理&am…

LabVIEW高效电磁阀性能测试

LabVIEW高效电磁阀性能测试 在核电站的安全运营中&#xff0c;电磁阀作为关键组件&#xff0c;其性能的可靠性至关重要。设计一套基于LabVIEW的电磁阀测试平台&#xff0c;既能精准测试电磁阀的多项性能指标&#xff0c;又能提高检修效率与准确性&#xff0c;进而保障核电站的…

Mock.js

在开发后端的应用中&#xff0c;我们使用postman来测试接口&#xff0c;观察和验证前后端之间的数据传递是否正常。 在开发前端的应用中&#xff0c;我们使用Mock.js来模拟后端服务&#xff0c;以便进行前端业务逻辑的开发和测试。 一般情况下&#xff0c;个人开发或者小团队开…

Codeforces Round 919 (Div. 2)题解(A-E)

https://codeforces.com/contest/1920 A Satisfying Constraints 链接&#xff1a;A - Satisfying Constraints 代码 #include <bits/stdc.h> using namespace std; int main() {int T;cin >> T;while(T--){int n;scanf("%d", &n);vector<int&…

算法沉淀——BFS 解决 FloodFill 算法(leetcode真题剖析)

算法沉淀——BFS 解决 FloodFill 算法 01.图像渲染02.岛屿数量03.岛屿的最大面积04.被围绕的区域 BFS&#xff08;广度优先搜索&#xff09;解决 Flood Fill 算法的基本思想是通过从起始点开始&#xff0c;逐层向外扩展&#xff0c;访问所有与起始点相连且具有相同特性&#xf…

docker (三)-开箱即用常用命令

一 docker架构 拉取镜像仓库中的镜像到本地&#xff0c;镜像运行产生一个容器 registry 镜像仓库 registry可以理解为镜像仓库&#xff0c;用于保存docker image。 Docker Hub 是docker官方的镜像仓库&#xff0c;docker命令默认从docker hub中拉取镜像。我们也可以搭建自己…

【Windows】删除 VHD 虚拟磁盘时提示“文件已在 System 中打开”的解决方法

一、原因 正如显示的那样&#xff0c;虚拟磁盘仍在被系统占用。因此我们需要断开磁盘与系统的连接。 二、解决方法 1. 在“开始”菜单中搜索“磁盘管理”&#xff0c;选择“创建并格式化硬盘分区”。 2. 右键点击需要删除的虚拟磁盘&#xff0c;选择“分离 VHD”。 3. 点击“…

laravel_stub type-hints的简单介绍

开发者介绍 存根文件的类型提示的功能是由Nuno Maduro&#xff08;右边的人&#xff09;提供的。 stub type-hints 指的是在 stub 文件中使用的类型提示&#xff08;type hints&#xff09;。 类型提示是 PHP 7 引入的一个特性&#xff0c;允许你在函数、方法和类的上下文中指…

day14笔记(多态)

多态 自己写多态演示遇见两个问题 1.在类里写show方法时犹豫要不要写参数,其实不用写参数也可以获取到类的信息 public void show(){//括号里面写参数吗System.out.println(getName()", "getAge());} 2.在测试类里面写方法时,写了一个show方法带参数,其实这里应该是…

Spring Boot 笔记 017 创建接口_新增文章

1.1实体类增加校验注释 1.1.1 自定义校验 1.1.1.1 自定义注解 package com.geji.anno;import com.geji.validation.StateValidation; import jakarta.validation.Constraint; import jakarta.validation.Payload; import jakarta.validation.constraints.NotEmpty;import jav…

【Redis快速入门】Redis三种集群搭建配置(主从集群、哨兵集群、分片集群)

个人名片&#xff1a; &#x1f43c;作者简介&#xff1a;一名大三在校生&#xff0c;喜欢AI编程&#x1f38b; &#x1f43b;‍❄️个人主页&#x1f947;&#xff1a;落798. &#x1f43c;个人WeChat&#xff1a;hmmwx53 &#x1f54a;️系列专栏&#xff1a;&#x1f5bc;️…