如何使用异步图像更新占位符图像?

How do I update a placeholder image with an async image?

我正在使用管理器 class 从缓存中提取图像或发出网络请求。我正在使用占位符图像。当检索到正确的图像时,替换该占位符图像的最佳方法是什么?

final ItemManager _manager;
final Item _item;
var _itemImage =
  new Image.asset('assets/images/icons/ic_placeholder.png');

@override
Widget build(BuildContext context) {
  _loadImage();
  return new Container(
    child: _itemImage,
  );
}

_loadImage() async {
  var file = await _manager.itemImageForImageUrl(_item.imageUrl);
  _stickerImage = new Image.file(file);
}

FutureBuilder class 就是为这种情况设计的。我会将图像 _loadImage 修改为 return 而不是设置成员变量。然后你可以摆脱 initState 并修改你的 build() 方法如下:

@override
Widget build(BuildContext context) {
  return new FutureBuilder(
    future: _loadImage(),
    builder: (BuildContext context, AsyncSnapshot<Image> image) {
      if (image.hasData) {
        return image.data;  // image is ready
      } else {
        return new Container();  // placeholder
      }
    },
  );
}

顺便说一句,你不应该在不调用 setState 的情况下改变 State 的成员变量。您的构建函数不会被调用,这是 linter 最终会抱怨的事情(一旦我们实现它)。但是 FutureBuilder 更适合您的用例,因为您不必担心如果您的状态在图像完成加载时被处置会发生什么。

我建议使用 flutter_image "to load images from the network with a retry mechanism."

您可以将它与这样的占位符配对:

new FadeInImage(
  placeholder: _itemImage,
  image: new NetworkImageWithRetry('https://example.com/img.jpg'),
),