如何在 Flutter 中使用 MemoryImage【Flutter 专题 23】

简介: 如何在 Flutter 中使用MemoryImage,Flutter 有一些 ImageProvider 的实现,其中之一是 MemoryImage,用于从内存中加载原始图像。由于图像数据已经在内存中,这是最快的 ImageProvider 类型。下面是 Flutter 的 ImgaeProvider 从最快到最慢的列表。MemoryImageAssetImageFileImageNetworkImage

如何在 Flutter 中使用MemoryImage

Flutter 有一些 ImageProvider 的实现,其中之一是 MemoryImage,用于从内存中加载原始图像。由于图像数据已经在内存中,这是最快的 ImageProvider 类型。下面是 Flutter 的 ImgaeProvider 从最快到最慢的列表。


  1. MemoryImage
  2. AssetImage
  3. FileImage
  4. NetworkImage


MemoryImage 的构造函数只有一个必填参数:bytes,类型为 Unit8List。它包含要解码成 image 的字节。另一个是可选的,是一个 double 值的 scale,使用 scale 来表示图像的大小。


MemoryImage(this.bytes, { this.scale = 1.0 })


您需要将图像数据设为 Unit8List 字节。要将图像转换为 Unit8List,您可以使用 Flutter 的 AssetBundle。 AssetBundle 的使用取决于图像的来源。


如果图像来自 assets,您可以按照下面的示例进行操作。


  Uint8List data = (await rootBundle.load('assets/images/pikachu.png'))
          .buffer
          .asUint8List();


上面的代码使用AssetBundleload方法来加载 assets 图像以获取Future<ByteData>。然后,使用 buffer 属性获取具有 asUint8List 方法的 ByteBuffer,用于获取可以传递给构造函数的适当数据类型。


如果图像来自网络,您可以通过类似的方式将其转换为 Uint8List,但您需要使用 NetworkAssetBundle,它扩展了 AssetBundle。


  Uint8List data = (await NetworkAssetBundle(Uri.parse('https://luckly007.oss-cn-beijing.aliyuncs.com'))
      .load("/image/image-20211124085239175.png")
  )
      .buffer
      .asUint8List();


有了所需的数据类型后,就很容易构造一个MemoryImage. 只需将数据作为第一个参数调用构造函数即可。或者,您还可以传递可选参数scale


MemoryImage(imageData, scale: 2))



下面是一个简单的应用程序,它使用 MemoryImage

import 'dart:typed_data';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Welcome to Flutter',
      home: MemoryImageApp(),
    );
  }
}
class MemoryImageApp extends StatefulWidget {
  @override
  _MemoryImageExampleState createState() {
    return _MemoryImageExampleState();
  }
}
class _MemoryImageExampleState extends State {
  late Uint8List imageData;
  @override
  void initState() {
    super.initState();
    loadAsset();
  }
  void loadAsset() async {
    Uint8List data = (await rootBundle.load('assets/images/pikachu.png'))
        .buffer
        .asUint8List();
    setState(() => this.imageData = data);
  }
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('坚果前端'),
      ),
      body: Center(child: _ImageWrapper()),
    );
  }
  Widget _ImageWrapper() {
    if (imageData == null) {
      return CircularProgressIndicator();
    }
    return Container(
      width: 150,
      height: 150,
      decoration: BoxDecoration(
        image: new DecorationImage(
            fit: BoxFit.cover, image: MemoryImage(imageData, scale: 0.5)),
      ),
    );
  }
}

首先,它将图像从 assets 转换为 Uint8List,然后将结果存储为状态变量。之后,图像数据用作 MemoryImage 的 bytes 属性。将可选的 scale 属性设置为 0.5 时,图像会按比例缩小。 不仅用于 BoxDecoration,它还可以用于任何具有 ImageProvider 类型属性的小部件,例如 Image 和 CircleImage

使用Image.Memory()命名构造函数

这是另一种创建 MemoryImage 的方法,它也需要图像的 Uint8List 数据。


下面是命名构造函数的基本用法

  image: new DecorationImage(
    fit: BoxFit.cover,
    image: Image.memory(imageData).image
  ),

您可以在构造函数中传递大量可用参数,如下所示。唯一需要的参数是bytes.


  • Uint8List bytes* : 图像数据。
  • Key key: 小部件键,用于控制是否应更换。
  • double scale: 如何缩放图像。默认为 1.0。
  • ImageFrameBuilder frameBuilder:负责创建代表此图像的小部件的构建器函数。
  • String semanticLabel:图像的语义描述。
  • bool excludeFromSemantics: 是否从语义中排除此图像。默认为false.
  • double width:图像的高度。
  • double height:图像的高度。
  • Color color:根据colorBlendMode值与图像混合的颜色。
  • BlendMode colorBlendMode:如何将颜色与图像结合起来。
  • BoxFit fit:如何将图像写入布局期间分配的空间。
  • AlignmentGeometry alignment:如何在其边界内对齐图像。
  • ImageRepeat repeat:如何绘制图像未覆盖的布局边界的任何部分。
  • Unit8List bytes*:图像数据。
  • Rect centerSlice:九块图像的中心切片。
  • bool matchTextDirection: 是否使用 的值TextDirection来绘制图像。默认为false.
  • bool gaplessPlayback:当图片提供者改变时是否继续显示旧图片。默认为false.
  • FilterQuality filterQuality:FilterQuality图片的。默认为FilterQuality.low.
  • int cacheWidth: 表示必须以指定的宽度对图像进行解码。
  • int cacheHeight:表示必须在指定高度解码图像。


*: 必需的


无论是使用 MemoryImage 构造函数还是 Image.Memory 命名构造函数,都需要先将图像数据设为 Uint8List。之后,只需将数据传递给构造函数即可显示图像。

相关文章
|
1月前
|
Android开发 iOS开发 容器
鸿蒙harmonyos next flutter混合开发之开发FFI plugin
鸿蒙harmonyos next flutter混合开发之开发FFI plugin
|
5月前
|
开发框架 前端开发 测试技术
Flutter开发常见问题解答
Flutter开发常见问题解答
|
30天前
|
开发者
鸿蒙Flutter实战:07-混合开发
鸿蒙Flutter混合开发支持两种模式:1) 基于har包,便于主项目开发者无需关心Flutter细节,但不支持热重载;2) 基于源码依赖,利于代码维护与热重载,需配置Flutter环境。项目结构包括AppScope、flutter_module等目录,适用于不同开发需求。
72 3
|
14天前
|
传感器 开发框架 物联网
鸿蒙next选择 Flutter 开发跨平台应用的原因
鸿蒙(HarmonyOS)是华为推出的一款旨在实现多设备无缝连接的操作系统。为了实现这一目标,鸿蒙选择了 Flutter 作为主要的跨平台应用开发框架。Flutter 的跨平台能力、高性能、丰富的生态支持和与鸿蒙系统的良好兼容性,使其成为理想的选择。通过 Flutter,开发者可以高效地构建和部署多平台应用,推动鸿蒙生态的快速发展。
121 0
|
16天前
|
Dart 安全 UED
Flutter&鸿蒙next中的表单封装:提升开发效率与用户体验
在移动应用开发中,表单是用户与应用交互的重要界面。本文介绍了如何在Flutter中封装表单,以提升开发效率和用户体验。通过代码复用、集中管理和一致性的优势,封装表单组件可以简化开发流程。文章详细讲解了Flutter表单的基础、封装方法和表单验证技巧,帮助开发者构建健壮且用户友好的应用。
56 0
|
1月前
|
开发框架 移动开发 Android开发
安卓与iOS开发中的跨平台解决方案:Flutter入门
【9月更文挑战第30天】在移动应用开发的广阔舞台上,安卓和iOS两大操作系统各自占据半壁江山。开发者们常常面临着选择:是专注于单一平台深耕细作,还是寻找一种能够横跨两大系统的开发方案?Flutter,作为一种新兴的跨平台UI工具包,正以其现代、响应式的特点赢得开发者的青睐。本文将带你一探究竟,从Flutter的基础概念到实战应用,深入浅出地介绍这一技术的魅力所在。
76 7
|
30天前
|
编解码 Dart API
鸿蒙Flutter实战:06-使用ArkTs开发Flutter鸿蒙插件
本文介绍了如何开发一个 Flutter 鸿蒙插件,实现 Flutter 与鸿蒙的混合开发及双端消息通信。通过定义 `MethodChannel` 实现 Flutter 侧的 token 存取方法,并在鸿蒙侧编写 `EntryAbility` 和 `ForestPlugin`,使用鸿蒙的首选项 API 完成数据的读写操作。文章还提供了注意事项和参考资料,帮助开发者更好地理解和实现这一过程。
56 0
|
30天前
|
Dart Android开发
鸿蒙Flutter实战:03-鸿蒙Flutter开发中集成Webview
本文介绍了在OpenHarmony平台上集成WebView的两种方法:一是使用第三方库`flutter_inappwebview`,通过配置pubspec.lock文件实现;二是编写原生ArkTS代码,自定义PlatformView,涉及创建入口能力、注册视图工厂、处理方法调用及页面构建等步骤。
48 0
|
2月前
|
JSON Dart Java
flutter开发多端平台应用的探索
flutter开发多端平台应用的探索
50 6
|
2月前
|
JSON Dart Java
flutter开发多端平台应用的探索 下 (跨模块、跨语言通信之平台通道)
flutter开发多端平台应用的探索 下 (跨模块、跨语言通信之平台通道)