2017-08-11 89 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"); 
     } 
    } 
} 

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

  • 顯示的東西代替圖像,直到它加載
  • 處理異常加載圖像(或事件不理會他們)
  • 聽「事件」有關圖像加載(前。當它被加載時做一些事情)