Flutter:如何优先显示来自 Asset 的图像,如果找不到,则显示来自 URL 的图像?

Posted

技术标签:

【中文标题】Flutter:如何优先显示来自 Asset 的图像,如果找不到,则显示来自 URL 的图像?【英文标题】:Flutter: How to prioritize displaying the image from Asset, if it can't be found, then display image from URL? 【发布时间】:2020-09-11 09:50:19 【问题描述】:

这是 JSON 文件:

[
  
    "id": 1,
    "country": "United States",
    "image": 
      "imageResName": "us.png",
      "imageUrl": "https://www.countryflags.io/US/shiny/64.png"
    
  ,
  
    "id": 2,
    "country": "Germany",
    "image": 
      "imageResName": "de.png",
      "imageUrl": "https://www.countryflags.io/DE/shiny/64.png"
    
  ,
  
    "id": 3,
    "country": "United Kingdom",
    "image": 
      "imageResName": "gb.png",
      "imageUrl": "https://www.countryflags.io/GB/shiny/64.png"
    
  
]

在资产中,我创建了 3 个图像文件:“us.png”、“de.png”、“gb.png”,并创建了一个 ListView 来显示 JSON 文件中的数据。所以我想设置以下条件:

1.首先在与imageResName 同名的资产中显示图像 (例如,带有country: United States 的“us.png”) 2.如果资产中找不到文件“us.png”,那么它将 从图像显示 imageUrl.

这是 main.dart 文件

import 'dart:convert';
import 'package:ask/country.dart';
import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatefulWidget 
  @override
  _MyAppState createState() => _MyAppState();


class _MyAppState extends State<MyApp> 
  Future<List<Country>> getCountryFromJson(BuildContext context) async 
    String jsonString =
        await DefaultAssetBundle.of(context).loadString('assets/country.json');
    List<dynamic> raw = jsonDecode(jsonString);
    return raw.map((e) => Country.fromJson(e)).toList();
  

  @override
  Widget build(BuildContext context) 
    return new MaterialApp(
        home: Scaffold(
            appBar: AppBar(title: Text('Country')),
            body: Container(
                child: FutureBuilder(
                    future: getCountryFromJson(context),
                    builder: (context, data) 
                      if (data.hasData) 
                        List<Country> countries = data.data;
                        return ListView.builder(
                            itemCount: countries.length,
                            itemBuilder: (context, index) 
                              return ListTile(
                                leading: CircleAvatar(
                                  backgroundImage: AssetImage('assets/$countries[index].image.imageResName                                  
                                  // 1. Prioritize displaying image from Asset
                                  // 2. If it can't find then display image from url
                                  // NetworkImage(countries[index].image.imageUrl),
                                ),
                                title: Text(countries[index].country),
                              );
                            );
                       else 
                        return Center(
                          child: CircularProgressIndicator(),
                        );
                      
                    ))));
  



【问题讨论】:

【参考方案1】:

我遇到了同样的问题。只需使用FadeInImage 如下:

FadeInImage(
                    width: 50,
                    height: 50,
                    fit: BoxFit.fill,
                    image: AssetImage(localPath),
                    placeholder: NetworkImage(urlPath),
              ),

确保您的 image: 是您的本地资产,而 placeholder: 是您的远程图像。

享受吧!

【讨论】:

【参考方案2】:

创建一个变量

String localImage = "assets/images/1.jpg";

这是你的逻辑,但你需要找到一种方法来检查 localImage 是否存在于本地 我不知道你为什么要这样做,这就是为什么我不能告诉你需要使用什么逻辑,但这是你的解决方案

leading: CircleAvatar(
// localImage = "assets/images/1.jpg"
    backgroundImage: localImage != null ? AssetImage(localImage) :  NetworkImage(countries[index].image.imageUrl),),

【讨论】:

我希望默认情况下,用户仍然会从资产加载图像以确保速度和体验,但是当我从 JSON 添加新国家/地区时,他们仍然会看到来自 http 的图像而无需更新应用程序获取新的资产文件。我试过你的方法还是不行,不知道是不是我做错了,请帮我看看,这是截图link 您已关闭,只需确保您的资产文件夹存在并且其中的图像存在,这就是为什么它给您一个错误它找不到资产文件夹我也没有看到它,您提供的屏幕截图不清楚 我认为它确实找到了资产文件夹,因为它仍然显示资产中的图像“de.png”和“gb.png”。我尝试删除图像“us.png”以查看它是否显示 NetworkImage,但它不起作用。我截了一张更清晰的截图here,如果我在某处做错了,请检查我 在您的资产中,我没有看到 us.png 图像,您的 localImage 不为空,它的值为 String,例如 localImage = "assets/us.png" 所以您的代码正在尝试查找字符串,但是它没有找到它所以它不会显示它并且因为它不是 null 它有一个字符串它不会显示网络图像这就是为什么我告诉你你需要创建一个逻辑来确定 localImage 是否不为 null,尝试更改 String localImage;它将工作并加载网络图像,因为 localImage;现在为空 哇,直到现在我才明白你的意思,我尝试打印它以确保它是 null 并且它有效:D link。感谢您的耐心等待。还有一个问题,如果我们不使用null来判断,有没有什么办法可以在Unable to load assets: assets / us.png的时候切换到NetworkImage

以上是关于Flutter:如何优先显示来自 Asset 的图像,如果找不到,则显示来自 URL 的图像?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Flutter web 上显示资产图像?

Flutter:如何显示来自 Firebase 的文本?

如何在 Flutter 中使用 Provider 显示来自 ChangeNotifier 的错误

在 Flutter 中,如何使用 CachedNetworkImage 显示来自 Firebase 的离线图像?

Flutter:显示来自 json 的数据

Dart/flutter:如何在模拟器的本地主机上显示来自 API 的图像