2017-08-11 49 views
2

这里我的用例是显示快餐栏,如果有错误,但由于我不打电话给load:我无法捕捉到SocketException。如何捕捉抖动解决NetworkImage时抛出的异常?

更新(例如堆栈跟踪):

I/flutter (11702): ══╡ EXCEPTION CAUGHT BY SERVICES ╞══════════════════════════════════════════════════════════════════ 
I/flutter (11702): The following SocketException was thrown resolving a single-frame image stream: 
I/flutter (11702): Connection failed (OS Error: Network is unreachable, errno = 101), address = ((snip)), port 
I/flutter (11702): = 443 
I/flutter (11702): When the exception was thrown, this was the stack: 
I/flutter (11702): #0  IOClient.send (package:http/src/io_client.dart:30:23) 
I/flutter (11702): <asynchronous suspension> 
I/flutter (11702): #1  BaseClient._sendUnstreamed (package:http/src/base_client.dart:171:38) 
I/flutter (11702): <asynchronous suspension> 
I/flutter (11702): #2  BaseClient.get (package:http/src/base_client.dart:34:5) 
I/flutter (11702): #3  NetworkImage._loadAsync (package:flutter/src/services/image_provider.dart:431:54) 
I/flutter (11702): <asynchronous suspension> 
I/flutter (11702): #4  NetworkImage.load (package:flutter/src/services/image_provider.dart:417:7) 
I/flutter (11702): #5  ImageProvider.resolve.<anonymous closure>.<anonymous closure> (package:flutter/src/services/image_provider.dart:253:61) 

回答

0

您仍然可以包装在一个try/catch此调用。 (小心,未经测试):

class _MyHomePageState extends State<MyHomePage> { 

    Widget _loadImage() { 
    NetworkImage image; 
    try { 
     image = new NetworkImage(url); 
     return image; 
    } catch (Exception) { 
     print(Exception); 
    } 
    return new Container(); 
    } 

    @override 
    Widget build(BuildContext context) { 
    return new Scaffold(
     appBar: new AppBar(
     title: new Text('TestProject'), 
    ), 
     body: new Center(
     child: _loadImage(), 
    ), 
    ); 
    } 
} 

您尝试加载图像。如果它被加载,该方法返回图像。否则,将捕获异常并返回一个空容器。

+1

感谢您的回答,但我不确定这是否正确。从文档中,NetworkImage是一个常量构造函数,图像的实际加载发生在ImageStreamCompleter中,而不是在创建ImageProvider时发生。 – perlatus

0

我比较确定这是不可能的使用NetworkImage,这是因为据我了解,只有在等待抛出异常的结果时才能捕获异常。

幸运的是,有一点F12动作看起来代码非常简单。所以我的解决方案是将NetworkImage的_loadAsync功能复制到我自己的类中,并带有一些小的tweeks。 (像rturning一个Uint8List,而不是一个编解码器)

utils的/ network_image_loader.dart

import 'package:flutter/services.dart'; 
import 'package:http/http.dart' as http; 
import 'dart:async'; 
import 'dart:typed_data'; 

class NetworkImageLoader { 
    String url; 
    Map<String, String> headers; 

    NetworkImageLoader(this.url, {this.headers}); 

    static final http.Client _httpClient = createHttpClient(); 

    Future<Uint8List> load() async { 
     final Uri resolved = Uri.base.resolve(this.url); 
     final http.Response response = await _httpClient.get(resolved, headers: headers); 
     if (response == null || response.statusCode != 200) 
     throw new Exception('HTTP request failed, statusCode: ${response?.statusCode}, $resolved'); 

     final Uint8List bytes = response.bodyBytes; 
     if (bytes.lengthInBytes == 0) 
     throw new Exception('NetworkImage is an empty file: $resolved'); 

     return bytes; 
    } 
} 

使用,这将是一个简单的方法(我用它不同,因为我是加载图像的一个循环,并显示默认情况下,所以我没有测试过这种方式,但它应该工作,或接近):

Widget img = new Text("Loading"); 

... 
    //Some function, ex constructor, init state, or a callback after you've done an http call 
    loadImage('http://imawesome.com'); 
... 

@override 
build(BuildContext context) { 
    return img; 
} 

Future<Uint8List> loadImage(String url) async { 
    try { 
     var netImg = new NetworkImageLoader(url); 
     var res = await netImg.load(); 
     setState(() { 
      img = new Image(image: new MemoryImage(data), 
       height: 100.0, 
       width: 100.0, 
       fit: BoxFit.contain, 
      ); 
     }); 
    } 
    on Exception { 
     setState(() { 
      img = new Text("Load Failed"); 
     } 
    } 
} 

所以,如果你想要做的任何以下的我的课是好的:

  • 显示的东西代替图像,直到它加载
  • 处理异常加载图像(或事件不理会他们)
  • 听“事件”有关图像加载(前。当它被加载时做一些事情)