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

Flutter富文本实现学习

Flutter 代码如何实现一个带有富文本显示和交互的页面。

前置知识点学习

RealRichText

`RealRichText` 和 `ImageSpan` 不是 Flutter 框架中内置的组件,而是自定义的组件或来自第三方库。这些组件的实现可以提供比标准 `RichText` 更丰富的功能,比如在富文本中插入图片、处理点击事件等。由于这些组件在标准 Flutter 中不存在,我将解释如何可能实现类似的功能。

TextSpan

`TextSpan` 是 Flutter 中用于构建富文本的基本组件之一。它允许你在同一个文本组件中混合和匹配不同的文本样式和手势识别功能。`TextSpan` 通常与 `RichText` 组件一起使用,以显示复杂的文本布局。

`TextSpan` 的基本结构

`TextSpan` 是一个不可变的、递归的数据结构,可以包含其他 `TextSpan`,从而允许嵌套不同的文本样式。

TextSpan({TextStyle? style,String? text,List<InlineSpan>? children,GestureRecognizer? recognizer,String? semanticsLabel,
})

关键属性

`style`:

  • 指定文本的样式,例如字体大小、颜色、粗细等。
  • 类型为 `TextStyle`。

`text`:

  • 要显示的文本字符串。
  • `text` 和 `children` 之间是互斥的,如果需要在一个 `TextSpan` 中显示多个文本片段,通常使用 `children`。

`children`:

  • 一个 `InlineSpan`(通常为 `TextSpan`)的列表,用于嵌套子文本。
  • 允许创建复杂的文本结构,如不同样式的文本段落。

`recognizer`:

  • 用于处理文本的手势识别,例如点击事件。
  • 通常使用 `TapGestureRecognizer` 来处理点击事件。

`semanticsLabel`:

  • 为文本提供一个可供屏幕阅读器使用的标签,帮助无障碍访问。

使用示例

下面是一个简单的例子,展示如何使用 `TextSpan` 来创建一个包含多种样式和交互的文本。

import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';class RichTextExample extends StatelessWidget {const RichTextExample({super.key});@overrideWidget build(BuildContext context) {return Scaffold(appBar: AppBar(title: const Text("Rich Text Example")),body: Center(child: RichText(text: TextSpan(text: 'Hello ',style: const TextStyle(color: Colors.black, fontSize: 18),children: <TextSpan>[const TextSpan(text: 'bold', style: TextStyle(fontWeight: FontWeight.bold)),const TextSpan(text: ' and ',),const TextSpan(text: 'italic',style: TextStyle(fontStyle: FontStyle.italic),),TextSpan(text: ' clickable ',style: const TextStyle(color: Colors.blue),recognizer: TapGestureRecognizer()..onTap = () {ScaffoldMessenger.of(context).showSnackBar(const SnackBar(content: Text('Clickable text clicked!')),);},),const TextSpan(text: 'text.',),],),),),);}
}

ImageSpan

`ImageSpan` 是一种在富文本中嵌入图片的技术。在 Flutter 中,虽然没有直接提供一个名为 `ImageSpan` 的组件,但你可以通过使用 `WidgetSpan` 来实现类似的功能。`WidgetSpan` 允许你在 `RichText` 中插入任意的 Flutter 小部件,包括图片。

使用 `WidgetSpan` 实现 `ImageSpan` 的功能

`WidgetSpan` 是 `InlineSpan` 的子类,可以在 `TextSpan` 列表中使用来嵌入小部件。通过这种方式,你可以在文本段落中插入图片或者其他小部件。

示例代码

import 'package:flutter/material.dart';class RichTextWithImageExample extends StatelessWidget {const RichTextWithImageExample({super.key});@overrideWidget build(BuildContext context) {return Scaffold(appBar: AppBar(title: const Text("Rich Text with Image Example")),body: Center(child: RichText(text: TextSpan(style: const TextStyle(color: Colors.black, fontSize: 18),children: <InlineSpan>[const TextSpan(text: 'This is an example of '),WidgetSpan(child: Image.asset("static/demo.png",width: 24,height: 24,)),const TextSpan(text: ' in a rich text widget.'),]),),),);}
}

解释

`RichText` 和 `TextSpan`:

  • `RichText` 用于显示复杂的文本布局,`TextSpan` 用于定义文本的样式和内容。

`WidgetSpan`:

  • `WidgetSpan` 可以嵌入任何小部件。在这个例子中,它用于插入一个图片。
  • `child` 属性接受一个 `Widget`,这里使用 `Image.asset` 来加载本地图片。

图片资源:

  • 确保图片路径正确,并在 `pubspec.yaml` 中声明图片资源。
  • 例如:
flutter:assets:- assets/demo.png

 使用场景

  • 图文混排: 当需要在同一个文本段落中展示图片和文本,比如图标、表情符号或其他装饰性元素。
  • 动态内容: 在文章或聊天应用中以富文本形式展示内容,图片作为内嵌元素。
  • 自定义格式: 创建带有图片的复杂格式文本,比如新闻应用中的插图或注释。

通过 `WidgetSpan`,你可以在 Flutter 的文本组件中灵活地插入图片和其他小部件,实现更复杂的文本布局和丰富的用户界面体验。

TapGestureRecognizer

`TapGestureRecognizer` 是 Flutter 中用于检测点击手势的一个手势识别器。它通常用于处理文本中的点击事件,特别是在 `TextSpan` 中,使得文本中的某些部分可以响应用户的点击操作。

基本使用

`TapGestureRecognizer` 是 `GestureRecognizer` 的一个子类,它专门用于处理点击(tap)事件。通常情况下,它与 `RichText` 和 `TextSpan` 结合使用,以实现文本的可点击功能。

如何使用 `TapGestureRecognizer`

以下是一个简单示例,展示如何在 `TextSpan` 中使用 `TapGestureRecognizer`,使得文本的一部分可以被点击并响应事件:

import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
class TapGestureExample extends StatelessWidget {const TapGestureExample({super.key});@overrideWidget build(BuildContext context) {return Scaffold(appBar: AppBar(title: const Text("Tap Gesture Recognizer Example")),body: Center(child: RichText(text: TextSpan(text: 'Click ',style: const TextStyle(color: Colors.black, fontSize: 18),children: <TextSpan>[TextSpan(text: 'here',style: const TextStyle(color: Colors.blue, decoration: TextDecoration.underline),recognizer: TapGestureRecognizer()..onTap = () {ScaffoldMessenger.of(context).showSnackBar(const SnackBar(content: Text('Text clicked!')),);},),const TextSpan(text: ' to see the effect.',),],),),),);}
}

 解释

`RichText` 和 `TextSpan`:

  • `RichText` 用于显示富文本。通过 `TextSpan`,你可以定义不同的文本样式和内容。

`TapGestureRecognizer`:

  • 创建一个 `TapGestureRecognizer` 实例并将其分配给 `TextSpan` 的 `recognizer` 属性。
  • 使用 `..onTap`(级联操作符)来定义 `onTap` 回调函数,当用户点击该文本时调用。

响应点击:

  • 在 `onTap` 回调中使用 `ScaffoldMessenger` 显示一个 `SnackBar`,以反馈用户的点击操作。

注意事项

释放资源:

  • 如果在有状态的小部件中使用 `TapGestureRecognizer`,请确保在 `dispose` 方法中调用 `dispose` 方法来释放手势识别器,以避免内存泄漏。

多手势识别:

  • `TapGestureRecognizer` 可以与其他类型的手势识别器一起使用。使用 `GestureDetector` 可以创建更复杂的手势识别场景。

用户体验:

  • 确保可点击的文本有视觉上的提示,如颜色变化或下划线,以便用户能够清楚地识别哪些文本是可交互的。

通过 `TapGestureRecognizer`,你可以为文本添加交互功能,使得应用的用户界面更加动态和响应用户操作。

富文本代码实现学习

import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
import 'package:gsy_flutter_demo/widget/rich/real_rich_text.dart';class RichTextDemoPage extends StatefulWidget {const RichTextDemoPage({super.key});@override_RichTextDemoState createState() => _RichTextDemoState();
}class _RichTextDemoState extends State<RichTextDemoPage> {@overrideWidget build(BuildContext mainContext) {return Scaffold(appBar: AppBar(title: const Text("RichTextDemoPage"),),body: Container(margin: const EdgeInsets.all(10),child: Builder(builder: (context) {return Center(child: RealRichText([TextSpan(text: "A Text Link",style: const TextStyle(color: Colors.red, fontSize: 14),recognizer: TapGestureRecognizer()..onTap = () {show(context, "Link Clicked.");},),ImageSpan(const AssetImage("static/demo.png"),imageWidth: 24,imageHeight: 24,),ImageSpan(const AssetImage("static/demo.png"),imageWidth: 24,imageHeight: 24,margin: const EdgeInsets.symmetric(horizontal: 10)),const TextSpan(text: "哈哈哈",style: TextStyle(color: Colors.yellow, fontSize: 14),),TextSpan(text: "@Somebody",style: const TextStyle(color: Colors.black,fontSize: 14,fontWeight: FontWeight.bold),recognizer: TapGestureRecognizer()..onTap = () {show(context, "Link Clicked.");},),TextSpan(text: " #RealRichText# ",style: const TextStyle(color: Colors.blue, fontSize: 14),recognizer: TapGestureRecognizer()..onTap = () {show(context, "Link Clicked.");},),const TextSpan(text: "showing a bigger image",style: TextStyle(color: Colors.black, fontSize: 14),),ImageSpan(const AssetImage("static/demo.png"),imageWidth: 24,imageHeight: 24,margin: const EdgeInsets.symmetric(horizontal: 5)),const TextSpan(text: "and seems working perfect……",style: TextStyle(color: Colors.black, fontSize: 14),),]),);}),),);}show(context, text) {ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text(text),action: SnackBarAction(label: 'ACTION',onPressed: () {ScaffoldMessenger.of(context).showSnackBar(const SnackBar(content: Text('You pressed snackbar\'s action.'),));},),));}
}

三方flutter库中的富文本实现源码

import 'dart:ui' as ui show Image;import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';/// According to the related Flutter Issues(#2022) ,
/// Inline-Image-In-Text is a long-time(2 years) missing feature since RichText(or the underlying Paragraph) does only support pure text.
/// But we can solve this problem in a simple/tricky way:
///
/// 1. Regarde the images as a particular blank TextSpan,
///   convert image's width and height to textspan's letterSpacing and fontSize.
///   the origin paragraph will do the layout operation and leave the desired image space for us.
/// 2. Override the paint function,
///   calculate the right offset via the getOffsetForCaret() api to draw the image over the space.
///
/// The only thing you have to do is converting your origin text to a TextSpan/ImageSpan List first.
///
/// {@tool sample}
///
/// ```dart
/// RealRichText([
///            TextSpan(
///              text: "showing a bigger image",
///              style: TextStyle(color: Colors.black, fontSize: 14),
///            ),
///            ImageSpan(
///              AssetImage("packages/real_rich_text/images/emoji_10.png"),
///              width: 40,
///              height: 40,
///            ),
///            TextSpan(
///              text: "and seems working perfect……",
///              style: TextStyle(color: Colors.black, fontSize: 14),
///            ),
///          ])
/// ```
/// {@end-tool}
///
class RealRichText extends Text {final List<TextSpan> textSpanList;const RealRichText(this.textSpanList, {super.key,TextStyle? style,TextAlign textAlign = TextAlign.start,TextDirection? textDirection,bool softWrap = true,TextOverflow overflow = TextOverflow.clip,TextScaler? textScaler,int? maxLines,Locale? locale,}) : super("",style: style,textAlign: textAlign,textDirection: textDirection,softWrap: softWrap,overflow: overflow,textScaler: textScaler,maxLines: maxLines,locale: locale);List<TextSpan> extractAllNestedChildren(TextSpan textSpan) {if (textSpan.children == null || textSpan.children!.isEmpty) {return [textSpan];}List<TextSpan> childrenSpan = [];for (var child in textSpan.children!) {childrenSpan.addAll(extractAllNestedChildren(child as TextSpan));}return childrenSpan;}@overrideWidget build(BuildContext context) {final DefaultTextStyle defaultTextStyle = DefaultTextStyle.of(context);TextStyle? effectiveTextStyle = style;if (style == null || style!.inherit) {effectiveTextStyle = defaultTextStyle.style.merge(style);}if (MediaQuery.boldTextOf(context)) {effectiveTextStyle =effectiveTextStyle!.merge(const TextStyle(fontWeight: FontWeight.bold));}TextSpan textSpan = TextSpan(style: effectiveTextStyle,text: "",children: extractAllNestedChildren(TextSpan(style: effectiveTextStyle,text: "",children: textSpanList,)));// pass the context to ImageSpan to create a ImageConfigurationfor (var f in textSpan.children!) {if (f is ImageSpan) {f.updateImageConfiguration(context);}}Widget result = _RichTextWrapper(textAlign: textAlign ?? defaultTextStyle.textAlign ?? TextAlign.start,textDirection: textDirection,// RichText uses Directionality.of to obtain a default if this is null.locale: locale,// RichText uses Localizations.localeOf to obtain a default if this is nullsoftWrap: softWrap ?? defaultTextStyle.softWrap,overflow: overflow ?? defaultTextStyle.overflow,textScaler: textScaler ?? MediaQuery.textScalerOf(context),maxLines: maxLines ?? defaultTextStyle.maxLines,text: textSpan);if (semanticsLabel != null) {result = Semantics(textDirection: textDirection,label: semanticsLabel,child: ExcludeSemantics(child: result,));}return result;}
}/// Since flutter engine does not support inline-image for now, we have to support this feature via a tricky solution:
/// convert image to a particular TextSpan whose text always be \u200B(a zero-width-space).
/// set letterSpacing by the required image width
/// set fontSize by the required image height
class ImageSpan extends TextSpan {final double imageWidth;final double imageHeight;final EdgeInsets? margin;final ImageProvider imageProvider;final ImageResolver imageResolver;ImageSpan(this.imageProvider, {this.imageWidth = 14.0,this.imageHeight = 14.0,this.margin,super.recognizer,})  : imageResolver = ImageResolver(imageProvider),super(style: TextStyle(color: Colors.transparent,letterSpacing:imageWidth + (margin == null ? 0 : margin.horizontal),height: 1,fontSize: (imageHeight / 1.15) +(margin == null ? 0 : margin.vertical)),text: "\u200B",children: []);void updateImageConfiguration(BuildContext context) {imageResolver.updateImageConfiguration(context, imageWidth, imageHeight);}double get width => imageWidth + (margin == null ? 0 : margin!.horizontal);double get height => imageHeight + (margin == null ? 0 : margin!.vertical);
}typedef ImageResolverListener = void Function(ImageInfo imageInfo, bool synchronousCall);class ImageResolver {final ImageProvider imageProvider;ImageStream? _imageStream;ImageConfiguration? _imageConfiguration;ui.Image? image;ImageResolverListener? _listener;ImageResolver(this.imageProvider);/// set the ImageConfiguration from outsidevoid updateImageConfiguration(BuildContext context, double width, double height) {_imageConfiguration = createLocalImageConfiguration(context,size: Size(width, height),);}ImageStreamListener? imageStreamListener;void resolve(ImageResolverListener listener) {assert(_imageConfiguration != null);final ImageStream? oldImageStream = _imageStream;_imageStream = imageProvider.resolve(_imageConfiguration!);assert(_imageStream != null);_listener = listener;if (_imageStream!.key != oldImageStream?.key) {if (imageStreamListener != null) {oldImageStream?.removeListener(imageStreamListener!);}imageStreamListener ??= ImageStreamListener(_handleImageChanged);_imageStream!.addListener(imageStreamListener!);}}void _handleImageChanged(ImageInfo imageInfo, bool synchronousCall) {image = imageInfo.image;_listener?.call(imageInfo, synchronousCall);}void addListening() {if (_listener != null) {imageStreamListener ??= ImageStreamListener(_handleImageChanged);_imageStream?.addListener(imageStreamListener!);}}void stopListening() {if (imageStreamListener != null) {_imageStream?.removeListener(imageStreamListener!);}}
}/// Just a subclass of RichText for overriding createRenderObject
/// to return a [_RealRichRenderParagraph] object
///
/// No more special purpose.
class _RichTextWrapper extends RichText {_RichTextWrapper({required TextSpan super.text,super.textAlign,super.textDirection,super.softWrap,super.overflow,super.textScaler,super.maxLines,super.locale,})  : assert(maxLines == null || maxLines > 0);@overrideRenderParagraph createRenderObject(BuildContext context) {assert(textDirection != null || debugCheckHasDirectionality(context));return _RealRichRenderParagraph(text as TextSpan,textAlign: textAlign,textDirection: textDirection ?? Directionality.of(context),softWrap: softWrap,overflow: overflow,textScaler: textScaler,maxLines: maxLines,locale: locale ?? Localizations.localeOf(context),);}
}/// paint the image on the top of those ImageSpan's blank space
class _RealRichRenderParagraph extends RenderParagraph {_RealRichRenderParagraph(TextSpan super.text,{required super.textAlign,required super.textDirection,required super.softWrap,required super.overflow,required super.textScaler,super.maxLines,super.locale});@overridevoid paint(PaintingContext context, Offset offset) {super.paint(context, offset);// Here it is!paintImageSpan(context, offset);}@overridevoid attach(covariant Object owner) {super.attach(owner as PipelineOwner);for (var textSpan in (text as TextSpan).children!) {if (textSpan is ImageSpan) {textSpan.imageResolver.addListening();}}}@overridevoid detach() {super.detach();for (var textSpan in (text as TextSpan).children!) {if (textSpan is ImageSpan) {textSpan.imageResolver.stopListening();}}}@overridevoid performLayout() {super.performLayout();debugPrint("size = $size");}/// this method draws inline-image over blank text space.void paintImageSpan(PaintingContext context, Offset offset) {final Canvas canvas = context.canvas;final Rect bounds = offset & size;debugPrint("_RealRichRenderParagraph offset=$offset bounds=$bounds");canvas.save();int textOffset = 0;for (TextSpan textSpanin (text as TextSpan).children as Iterable<TextSpan>) {if (textSpan is ImageSpan) {// this is the top-center point of the ImageSpanOffset offsetForCaret = getOffsetForCaret(TextPosition(offset: textOffset),bounds,);// found this is a overflowed image. ignore itif (textOffset != 0 &&offsetForCaret.dx == 0 &&offsetForCaret.dy == 0) {return;}// this is the top-left point of the ImageSpan.// Usually, offsetForCaret indicates the top-center offset// except the first text which is always (0, 0)Offset topLeftOffset = Offset(offset.dx +offsetForCaret.dx -(textOffset == 0 ? 0 : textSpan.width / 2),offset.dy + offsetForCaret.dy);debugPrint("_RealRichRenderParagraph ImageSpan, textOffset = $textOffset, offsetForCaret=$offsetForCaret, topLeftOffset=$topLeftOffset");// if image is not ready: wait for async ImageInfoif (textSpan.imageResolver.image == null) {textSpan.imageResolver.resolve((imageInfo, synchronousCall) {if (synchronousCall) {paintImage(canvas: canvas,rect: topLeftOffset & Size(textSpan.width, textSpan.height),image: textSpan.imageResolver.image!,fit: BoxFit.scaleDown,alignment: Alignment.center);} else {if (owner == null || !owner!.debugDoingPaint) {markNeedsPaint();}}});textOffset += textSpan.toPlainText().length;continue;}// else: just paint it. bottomCenter Alignment seems better...paintImage(canvas: canvas,rect: topLeftOffset & Size(textSpan.width, textSpan.height),image: textSpan.imageResolver.image!,fit: BoxFit.scaleDown,alignment: Alignment.center);}textOffset += textSpan.toPlainText().length;}canvas.restore();}
}

相关文章:

Flutter富文本实现学习

Flutter 代码如何实现一个带有富文本显示和交互的页面。 前置知识点学习 RealRichText RealRichText 和 ImageSpan 不是 Flutter 框架中内置的组件&#xff0c;而是自定义的组件或来自第三方库。这些组件的实现可以提供比标准 RichText 更丰富的功能&#xff0c;比如在富文本…...

如何解决 OpenAI API 连接问题:降级 urllib3 版本

如何解决 OpenAI API 连接问题&#xff1a;降级 urllib3 版本 在使用 OpenAI API 时&#xff0c;很多开发者可能会遇到连接问题&#xff0c;特别是在使用 Python 代码与 OpenAI 进行交互时。常见的错误包括 ProxyError、SSLError 和 MaxRetryError&#xff0c;它们通常表示在通…...

【C语言】库函数常见的陷阱与缺陷(三):内存分配函数[4]--free

C语言中的free函数用于释放之前通过malloc、calloc或realloc动态分配的内存。然而,在使用free函数时,开发者可能会遇到一些陷阱和缺陷。 一、功能与用法 free 函数是 C 语言中用于释放动态分配内存的关键函数。在程序使用 malloc、calloc 或 realloc 等函数在堆上分配了内存…...

论文分享 | PromptFuzz:用于模糊测试驱动程序生成的提示模糊测试

大语言模型拥有的强大能力可以用来辅助多种工作&#xff0c;但如何有效的辅助仍然需要人的精巧设计。分享一篇发表于2024年CCS会议的论文PromptFuzz&#xff0c;它利用模型提示生成模糊测试驱动代码&#xff0c;并将代码片段嵌入到LLVM框架中执行模糊测试。 论文摘要 制作高质…...

AWS K8s 部署架构

Amazon Web Services&#xff08;AWS&#xff09;提供了一种简化的Kubernetes&#xff08;K8s&#xff09;部署架构&#xff0c;使得在云环境中管理和扩展容器化应用变得更加容易。这个架构的核心是AWS EKS&#xff08;Elastic Kubernetes Service&#xff09;&#xff0c;它是…...

JavaSE笔记(四)

Java泛型与集合类 在前面我们学习了最重要的类和对象,了解了面向对象编程的思想,注意,非常重要,面向对象是必须要深入理解和掌握的内容,不能草草结束。在本章节,我们会继续深入了解,从我们的泛型开始,再到我们的数据结构,最后再开始我们的集合类学习。 走进泛型 为…...

C语言基础——指针(5)

一&#xff0e; 函数指针变量 1. 函数指针变量的定义&#xff1a; 类比数组指针变量&#xff0c;数组指针变量是存放数组地址的变量&#xff0c;那么同理&#xff0c;函数指针变量就是存放函数地址的变量。 2. 创建函数指针变量&#xff1a; 函数是有地址的&#xff0…...

curl+openssl 踩坑笔记

curl编译&#xff1a;点击跳转 踩坑一 * SSL certificate problem: unable to get local issuer certificate * closing connection #0 curl: (60) SSL certificate problem: unable to get local issuer certificate More details here: https://curl.se/docs/sslcerts.html …...

Unity 实现Canvas显示3D物体

新建一个UI相机&#xff0c;选择渲染层为UI 将主相机的渲染层去掉UI层 、 将Canvas的RenderMode设置为Screen Space - Camera,将RenderCamera设置为UI相机 新建3D物体的UI父物体&#xff0c;并将3D物体的层级设置为UI层 适当的放缩3DObjParent&#xff0c;让3D物体能显示出来…...

【Docker命令】如何使用`docker exec`在容器内执行命令

大家好&#xff0c;今天我们来聊聊Docker容器管理中的一个非常有用的命令&#xff1a;docker exec。在日常工作中&#xff0c;我们经常需要在运行中的Docker容器内执行各种命令&#xff0c;docker exec正是帮助我们实现这一需求的利器。下面我将通过一个简单的例子&#xff0c;…...

NetSuite Formula(HTML)超链打开Transaction

当Saved Search作为Sublist应用在Form时&#xff0c;如果Document Number是Group过的&#xff0c;则会出现如下超链失效的情况。 解决办法&#xff1a; 可以利用Saved Search中的Formula&#xff08;HTML&#xff09;功能来构建超链&#xff0c;用于打开Transaction。 以下图…...

【React】- 跨域PDF预览、下载(改文件名)、打印

我们经常会碰到跨域来方位PDF&#xff0c;同时需要下载、打印的需求&#xff0c;通常由于浏览器的安全策略&#xff0c;可以预览&#xff0c;但是下载和打印可能会受限&#xff0c;这时候怎么办呢&#xff1f; 1.创建一个隐藏的标签 要下载 iframe 中的 PDF 文件&#xff0c;…...

git clone ssh 设置代理

Linux配置方法 编辑 ~/.ssh/config 文件 Host github.com Hostname github.com ProxyCommand nc -v -x 127.0.0.1:1080 %h %pwindows配置方法 编辑 C:\Users\当前用户名.ssh\config 文件 Host github.com Hostname github.com ProxyCommand connect -S 127.0.0.1:1080 %h %…...

RK3568平台(USB篇)USB网络共享

使用RK的USB网络共享,在内核里面已经有了,这不需要自己写驱动程序,只需要把内核自带的USB网络共享的驱动添加上去即可。 一.RNDIS 协议简介 RNDIS 是微软定义的一种协议,它允许通过 USB 接口实现网络连接。通过 RNDIS,USB 设备可以充当网络适配器,允许主机通过 USB 与设…...

vite 打包时:JavaScript heap out of memory(内存溢出)

出错原因分析&#xff1a; 执行命令 npm run build 时出现以下错误提示&#xff1a; vite v3.2.7 building for production... 11:22:34 transforming (3) src\main.tsWARN Browserslist: caniuse…...

【服务器学习专栏 1.2 -- 带外管理】

请阅读 嵌入式学习必备专栏 文章目录 Overview服务器带外管理BMC 介绍BMC 特点BMC 工作原理 Overview 从技术的角度&#xff0c;网络管理可分为带外管理&#xff08;out-of-band&#xff09;和带内管理&#xff08;in-band&#xff09;两种管理模式。 带内管理&#xff0c;是指…...

微服务のGeteWay

目录 概念&#xff1a; 三大核心&#xff1a; 工作流程&#xff1a; 9527网关如何做路由映射&#xff1a; GetWay高级特性&#xff1a; 按服务名动态路由服务&#xff1a; 断言Route Predicate Factories &#xff1a; 获取当前时区时间&#xff1a; After Route &…...

html+css+js网页设计 美食 美食家6个页面

htmlcssjs网页设计 美食 美食家6个页面 网页作品代码简单&#xff0c;可使用任意HTML辑软件&#xff08;如&#xff1a;Dreamweaver、HBuilder、Vscode 、Sublime 、Webstorm、Text 、Notepad 等任意html编辑软件进行运行及修改编辑等操作&#xff09;。 获取源码 1&#xf…...

IntelliJ Idea常用快捷键详解

文章目录 IntelliJ Idea常用快捷键详解一、引言二、文本编辑与导航1、文本编辑2、代码折叠与展开 三、运行和调试四、代码编辑1、代码补全 五、重构与优化1、重构 六、使用示例代码注释示例代码补全示例 七、总结 IntelliJ Idea常用快捷键详解 一、引言 在Java开发中&#xff…...

服务器虚拟化:它是什么以及有什么好处?

运行虚拟服务器有助于创建更高效的 IT 基础架构。 随着业务每天收集的数据量逐年激增&#xff0c;传统的物理服务器已经无法单独满足业务需求。 相反&#xff0c;许多组织正在转向虚拟化的力量。 这是我们创建物理实体的虚拟版本的过程&#xff0c;在计算中&#xff0c;通常指…...

Python爬虫完整代码拿走不谢

对于新手做Python爬虫来说是有点难处的&#xff0c;前期练习的时候可以直接套用模板&#xff0c;这样省时省力还很方便。 使用Python爬取某网站的相关数据&#xff0c;并保存到同目录下Excel。 直接上代码&#xff1a; import re import urllib.error import urllib.request…...

MLA:多头潜在注意力

MLA:多头潜在注意力 多头潜在注意力(MLA)机制是一种在深度学习模型中用于处理序列数据的注意力机制的改进形式,以下是对其原理和示例的详细介绍: 原理 低秩键值联合压缩:MLA机制利用低秩键值联合压缩来消除注意力模块中的某些计算,从而提高模型的运行速度和性能。在传…...

阿里云大模型ACP高级工程师认证模拟试题

阿里云大模型ACP高级工程师认证模拟试题 0. 引言1. 模拟试题单选题多选题单选题多选题单选题多选题单选题多选题单选题多选题单选题多选题单选题多选题单选题多选题单选题多选题单选题多选题单选题多选题单选题多选题单选题多选题单选题单选题单选题多选题多选题单选题多选题单…...

游戏引擎学习第67天

reviewing “apron”概念以更新区域 我们正在进行模拟区域的扩展工作&#xff0c;目标是通过增加一个更大的区域来支持更丰富的互动&#xff0c;尤其是那些可能超出摄像机视野的内容。现有的模拟区域包括摄像机能看到的区域和其周围的环境区域&#xff0c;但为了保证更高效的游…...

Nginx知识详解(理论+实战更易懂)

目录 一、Nginx架构和安装 1.1 Nginx 概述 1.1.1 nginx介绍 1.1.2?Nginx 功能介绍 1.1.3?基础特性 1.1.4?Web 服务相关的功能 1.2?Nginx 架构和进程 1.2.1?Nginx 进程结构 1.2.2?Nginx 进程间通信 1.2.3?Nginx 启动和 HTTP 连接建立 1.2.4?HTTP 处理过程 1…...

# 【鸿蒙开发】多线程之Worker的使用

【鸿蒙开发】多线程之Worker的使用 文章目录 【鸿蒙开发】多线程之Worker的使用前言一、Worker的介绍二、注意事项三、Worker使用示例1.新建一个Worker2.主线程使用Worker3.子线程Worker的使用 四、效果展示 前言 本文主要介绍了多线程的方法之一&#xff0c;使用Worker开启多…...

TKG-DM – 基于Latent Diffusion模型的“原生”色度提取生成具有透明通道的图像

概述 原文地址&#xff1a;https://www.unite.ai/improving-green-screen-generation-for-stable-diffusion/ 论文地址&#xff1a;https://arxiv.org/pdf/2411.15580 尽管社区研究和投资者对图像生成人工智能充满热情&#xff0c;但此类系统的输出并不总是可以直接用于产品开…...

告别 Windows 迟缓!多维度优化策略开启流畅新体验

在日常使用 Windows 系统的过程中&#xff0c;随着时间推移和软件安装卸载&#xff0c;系统可能会出现运行缓慢、卡顿等问题。本文中简鹿办公将详细介绍一系列 Windows 系统优化方法&#xff0c;涵盖多个关键层面&#xff0c;助力您的电脑重焕生机。 一、磁盘清理与优化 磁盘…...

亚马逊国际站商品爬虫:Python实战指南

在数字化时代&#xff0c;数据的价值不言而喻。对于电商领域而言&#xff0c;获取竞争对手的商品信息、价格、评价等数据&#xff0c;对于市场分析和策略制定至关重要。本文将带你了解如何使用Python编写爬虫&#xff0c;以亚马逊国际站为例&#xff0c;按照关键字搜索并获取商…...

RabbitMQ基础篇之Java客户端快速入门

文章目录 需求 项目设置与依赖管理 配置RabbitMQ的连接信息创建队列与消息发送创建消费者&#xff08;消息接收&#xff09;环境准备与操作 需求 利用控制台创建队列 simple.queue在 publisher 服务中&#xff0c;利用 SpringAMQP 直接向 simple.queue 发送消息在 consumer 服…...