Flutter网络图片加载插件url_image的使用

发布于 1周前 作者 itying888 来自 Flutter

Flutter网络图片加载插件url_image的使用

UrlImage 是一个跨平台的小部件,用于从网络通过URL加载远程图像并支持持久缓存。该小部件支持Flutter支持的所有光栅图像格式,以及SVG图像。

如果您需要从网络显示SVG图片或需要持久缓存以快速在应用重启后显示远程图像,那么 UrlImage 可能是一个不错的选择。

示例动画

功能特性

  • 通过URL从网络显示图像,包括光栅和矢量格式。
  • 将图像存储在持久缓存中,因此当应用程序重新启动时,所有之前下载的图像将立即从文件存储中显示出来。
  • 即使最后一个小部件被释放,图像提供者也不会从内存缓存中移除,因此当小部件再次出现在屏幕上时,图像会立即显示。
  • 平滑地更新内部存储。如果远程存储中先前下载的图像发生了变化,小部件将显示更改动画。
  • 自定义占位符构建器,即加载小部件构建器和错误小部件构建器。
  • 自定义文件存储、下载器和矢量解码器。
  • 支持使用标准的 logging 包进行消息日志记录,并且可以自定义日志级别。
  • 可选的通知,例如成功或失败尝试加载图像,或者以原始尺寸显示图像(这在图像用作照片查看器画廊时可能很有用)。
  • 可以像普通小部件一样绘制图像,也可以作为墨水绘制在底层材料上,因此图像上会出现褶皱。

开始使用

首先,在项目中添加 url_image 包并导入它:

flutter pub add url_image
import 'package:url_image/url_image.dart';

然后配置 config,提供自定义委托:

UrlImage.config
  ..fileStorage = MyFileStorage()
  ..downloader = const MyDownloader()
  ..vectorDecoder = const MyVectorDecoder()
;

您需要首先使用项目中首选的工具实现这些委托。例如,您可以使用 httpdio 来实现 DownloadDelegate,或者您可能已经实现了自己的HTTP客户端,或者您可以编写提供自定义头和需要授权请求的特殊图像仓库。

如果不提供任何委托,当试图使用委托时,小部件将在日志中显示相应的消息。

FileStorageDelegate

此委托为 UrlImageCache 提供功能,使其能够从文件存储中存储和加载图像。它是可选的。如果不提供此委托,当应用程序重新启动时,小部件不会从文件存储中恢复数据,因此所有图像将以某些延迟出现(需要一些时间才能从互联网下载图像)。

DownloadDelegate

此委托负责使用其URL下载图像。您可以按您希望的方式实现下载方法,但最终您必须向小部件提供下载图像的字节和格式(光栅/矢量)。这也是可选的,但几乎不会在不从网络下载图像的情况下使用 UrlImage

VectorDecodeDelegate

您可能需要从网络显示SVG图片。借助此委托,UrlImage 可以显示SVG图片。这很简单,只需导入 flutter_svg 包并在实现的委托中使用它来解码SVG图片,如下所示:

[@override](/user/override)
Future<VectorInfo> decode(final Uint8List bytes, {
  bool clipViewbox = true,
}) async
{
  final info = await vg.loadPicture(SvgBytesLoader(bytes), null,
    clipViewbox: clipViewbox,
  );
  return VectorInfo(info.picture, info.size);
}

就这样!现在您可以使用 UrlImage 小部件下载并显示SVG图片,只需指定SVG图片的URL即可,就像对其他位图图像一样。

您可以在该包的 example 项目中看到实现示例。

日志记录

如果您使用 logging 包,可以为小部件提供日志级别,如下所示:

Logger.root.level = Level.ALL;
Logger.root.onRecord.listen(onMessage);
UrlImage.config.logLevel = Level.OFF;

使用方式

然后您只需像通常使用 ImageImage.network 小部件一样在您的小部件树中使用 UrlImage

UrlImage(
  name: 'user_profile',
  url: user.pictureUrl,
  fit: BoxFit.contain,
),

示例代码

以下是完整的示例代码,展示了如何使用 UrlImage 插件。

import 'dart:developer';

import 'package:flutter/material.dart';
import 'package:logging/logger.dart';
import 'package:url_image/url_image.dart';

import 'downloader.dart';
import 'file_storage.dart';
import 'vector_decoder.dart';

Future<void> main() async {
  Logger.root.level = Level.ALL;
  Logger.root.onRecord.listen(onMessage);
  UrlImage.config
    ..fileStorage = MyFileStorage()
    ..downloader = const MyDownloader()
    ..vectorDecoder = const MyVectorDecoder();
  await Future.delayed(const Duration(seconds: 2));
  runApp(const MyApp());
}

void onMessage(final LogRecord record) {
  var msg = '${record.level.name[0]} ${record.time} ${record.message}';
  if (record.error != null) {
    msg += ' (${record.error})';
  }
  log(msg,
    time: record.time,
    sequenceNumber: record.sequenceNumber,
    level: record.level.value,
    name: record.loggerName,
    zone: record.zone,
    error: record.error,
    stackTrace: record.stackTrace,
  );
}

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

  [@override](/user/override)
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
        useMaterial3: true,
      ),
      home: const MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  final String title;

  const MyHomePage({super.key, required this.title});

  [@override](/user/override)
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  static const urls = [
    'https://raw.githubusercontent.com/darkstarx/url_image/main/example/media/nature1.jpg',
    'https://raw.githubusercontent.com/darkstarx/url_image/main/example/media/nature2.jpg',
    'https://raw.githubusercontent.com/darkstarx/url_image/main/example/media/nature1.svg',
    'https://raw.githubusercontent.com/darkstarx/url_image/main/example/media/nature2.svg',
  ];

  [@override](/user/override)
  Widget build(final BuildContext context) {
    final url = urls[_index];
    final name = Uri.parse(url).pathSegments.last;
    return Scaffold(
      appBar: AppBar(title: Text(widget.title)),
      body: InkWell(
        onTap: () {},
        child: Column(
          children: [
            Expanded(
              child: Center(
                child: UrlImage(name: name, url: url),
              ),
            ),
            const SizedBox(height: kToolbarHeight),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () => setState(() {
          if (++_index >= urls.length) _index = 0;
        }),
        child: const Icon(Icons.navigate_next),
      ),
    );
  }

  var _index = 0;
}

更多关于Flutter网络图片加载插件url_image的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter网络图片加载插件url_image的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


当然,以下是如何在Flutter项目中使用url_image插件来加载网络图片的示例代码。不过需要注意的是,截至我最后更新的时间(2023年),url_image并不是一个广为人知的官方或广泛使用的Flutter插件。更常见的选择是使用Flutter社区广泛采用的cached_network_image插件。但为了符合你的要求,我会假设url_image插件的使用方式类似于其他图像加载插件,并给出一个假设性的示例。

首先,确保你的pubspec.yaml文件中已经添加了url_image插件的依赖(注意:如果url_image实际上不存在,你需要替换为如cached_network_image这样的实际插件)。

dependencies:
  flutter:
    sdk: flutter
  url_image: ^x.y.z  # 假设的版本号,实际使用时请替换为最新版本

然后运行flutter pub get来安装依赖。

接下来,在你的Dart代码中,你可以这样使用url_image(假设性的用法,实际使用时请参考插件的官方文档):

import 'package:flutter/material.dart';
import 'package:url_image/url_image.dart'; // 假设的导入路径

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text('URL Image Example'),
        ),
        body: Center(
          child: UrlImage.network(
            'https://example.com/path/to/your/image.jpg', // 替换为你的图片URL
            placeholder: (context, url) => CircularProgressIndicator(), // 加载中的占位符
            errorWidget: (context, url, error) => Icon(Icons.error), // 加载失败的错误图标
          ),
        ),
      ),
    );
  }
}

在这个示例中,UrlImage.network方法用于从指定的URL加载网络图片。我们提供了两个可选参数:

  1. placeholder:一个函数,返回一个Widget,用于在图片加载时显示。在这个例子中,我们使用了CircularProgressIndicator作为占位符。
  2. errorWidget:一个函数,返回一个Widget,用于在图片加载失败时显示。在这个例子中,我们使用了Icon(Icons.error)作为错误图标。

请注意,由于url_image可能并不是一个真实存在的插件,上述代码是基于假设的用法。如果你发现url_image不存在或文档不足,建议使用cached_network_image插件,它提供了类似的功能,并且社区支持广泛。以下是使用cached_network_image的示例:

dependencies:
  flutter:
    sdk: flutter
  cached_network_image: ^3.1.0  # 使用最新版本

然后在你的Dart代码中:

import 'package:flutter/material.dart';
import 'package:cached_network_image/cached_network_image.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text('Cached Network Image Example'),
        ),
        body: Center(
          child: CachedNetworkImage(
            imageUrl: 'https://example.com/path/to/your/image.jpg', // 替换为你的图片URL
            placeholder: (context, url) => CircularProgressIndicator(), // 加载中的占位符
            errorWidget: (context, url, error) => Icon(Icons.error), // 加载失败的错误图标
          ),
        ),
      ),
    );
  }
}

这个示例与前面的假设性url_image用法非常相似,但CachedNetworkImage是一个真实存在且广泛使用的插件。

回到顶部