Commit c12c019b authored by Jason Simmons's avatar Jason Simmons Committed by GitHub

Throw an exception with the asset key if a string asset load fails (#9325)

Fixes https://github.com/flutter/flutter/issues/7715
parent 9dfcc6ec
...@@ -51,10 +51,14 @@ import 'platform_messages.dart'; ...@@ -51,10 +51,14 @@ import 'platform_messages.dart';
/// * [rootBundle] /// * [rootBundle]
abstract class AssetBundle { abstract class AssetBundle {
/// Retrieve a binary resource from the asset bundle as a data stream. /// Retrieve a binary resource from the asset bundle as a data stream.
///
/// Throws an exception if the asset is not found.
Future<ByteData> load(String key); Future<ByteData> load(String key);
/// Retrieve a string from the asset bundle. /// Retrieve a string from the asset bundle.
/// ///
/// Throws an exception if the asset is not found.
///
/// If the `cache` argument is set to false, then the data will not be /// If the `cache` argument is set to false, then the data will not be
/// cached, and reading the data may bypass the cache. This is useful if the /// cached, and reading the data may bypass the cache. This is useful if the
/// caller is going to be doing its own caching. (It might not be cached if /// caller is going to be doing its own caching. (It might not be cached if
...@@ -97,15 +101,20 @@ class NetworkAssetBundle extends AssetBundle { ...@@ -97,15 +101,20 @@ class NetworkAssetBundle extends AssetBundle {
@override @override
Future<ByteData> load(String key) async { Future<ByteData> load(String key) async {
final http.Response response = await _httpClient.get(_urlFromKey(key)); final http.Response response = await _httpClient.get(_urlFromKey(key));
if (response.statusCode == 200) if (response.statusCode != 200)
return null; throw new FlutterError('Unable to load asset: $key');
return response.bodyBytes.buffer.asByteData(); return response.bodyBytes.buffer.asByteData();
} }
@override @override
Future<String> loadString(String key, { bool cache: true }) async { Future<String> loadString(String key, { bool cache: true }) async {
final http.Response response = await _httpClient.get(_urlFromKey(key)); final http.Response response = await _httpClient.get(_urlFromKey(key));
return response.statusCode == 200 ? response.body : null; if (response.statusCode != 200)
throw new FlutterError(
'Unable to load asset: $key\n'
'HTTP status code: ${response.statusCode}'
);
return response.body;
} }
/// Retrieve a string from the asset bundle, parse it with the given function, /// Retrieve a string from the asset bundle, parse it with the given function,
...@@ -149,6 +158,8 @@ abstract class CachingAssetBundle extends AssetBundle { ...@@ -149,6 +158,8 @@ abstract class CachingAssetBundle extends AssetBundle {
Future<String> _fetchString(String key) async { Future<String> _fetchString(String key) async {
final ByteData data = await load(key); final ByteData data = await load(key);
if (data == null)
throw new FlutterError('Unable to load asset: $key');
return UTF8.decode(data.buffer.asUint8List()); return UTF8.decode(data.buffer.asUint8List());
} }
...@@ -202,9 +213,13 @@ abstract class CachingAssetBundle extends AssetBundle { ...@@ -202,9 +213,13 @@ abstract class CachingAssetBundle extends AssetBundle {
/// An [AssetBundle] that loads resources using platform messages. /// An [AssetBundle] that loads resources using platform messages.
class PlatformAssetBundle extends CachingAssetBundle { class PlatformAssetBundle extends CachingAssetBundle {
@override @override
Future<ByteData> load(String key) { Future<ByteData> load(String key) async {
final Uint8List encoded = UTF8.encoder.convert(key); final Uint8List encoded = UTF8.encoder.convert(key);
return PlatformMessages.sendBinary('flutter/assets', encoded.buffer.asByteData()); final ByteData asset =
await PlatformMessages.sendBinary('flutter/assets', encoded.buffer.asByteData());
if (asset == null)
throw new FlutterError('Unable to load asset: $key');
return asset;
} }
} }
......
// Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'dart:async';
import 'dart:typed_data';
import 'package:flutter/foundation.dart';
import 'package:flutter/services.dart';
import 'package:flutter_test/flutter_test.dart';
class TestAssetBundle extends CachingAssetBundle {
Map<String, int> loadCallCount = <String, int>{};
@override
Future<ByteData> load(String key) async {
loadCallCount[key] = loadCallCount[key] ?? 0 + 1;
if (key == 'one')
return new ByteData(1)..setInt8(0, 49);
throw new FlutterError('key not found');
}
}
void main() {
test('Caching asset bundle test', () async {
final TestAssetBundle bundle = new TestAssetBundle();
final ByteData assetData = await bundle.load('one');
expect(assetData.getInt8(0), equals(49));
expect(bundle.loadCallCount['one'], 1);
final String assetString = await bundle.loadString('one');
expect(assetString, equals('1'));
expect(bundle.loadCallCount['one'], 1);
FlutterError loadException;
try {
await bundle.loadString('foo');
} catch (e) {
loadException = e;
}
expect(loadException, isFlutterError);
});
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment