Repository: flutter
Issue: App which loading large json files crushes when using flutter drive
Labels: framework,t: flutter driver,a: assets,P2,team-framework,triaged-framework

I'm writing an app, that supports multiple languages. All translation strings are stored in locale folder in json files (one for each language). This files are loaded as the app starts.

To load data, I use loadString method from AssetBundle class, from flutter/services package. It works fine when I run the app but when I want to test the app with flutter drive, I encounter an issue. If the translation file is 10240 bytes or bigger, the app crashes on test start.

I found, that when the file is 10240 bytes or larger, the loadString method uses different way to load file content, for the performance purposes. I did a workaround by using a step-back load method while testing and then getting string on my own regardless of the size.

To reproduce this, I made a small app from flutter demo app. The main file stays almost the same, with exception of creating MaterialApp object, where I add a translation delegate. The translation is handled by translation.dart file. For the reproducing the issue, there is also needed a json file in locale directory, named "i18n_en_US.json" and with size larger than 10239 bytes.

The issue only occurs while using flutter drive test so there is also a test_driver directory, which contains the app.dart file and app_count_test.dart file. This test is to run the app and tap on Increment button one time. To run test I use "flutter drive --target=test_driver/app.dart --driver=test_driver/app_count_test.dart" command.

```
import 'package:flutter/material.dart';

import 'package:json_test/translations.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      localizationsDelegates: [TranslationsDelegate()],
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);

  final String title;

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  int _counter = 0;

  void _incrementCounter() {
    setState(() {
      _counter++;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              '$_counter',
              style: Theme.of(context).textTheme.display1,
            ),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        key: Key('increment_key'),
        onPressed: _incrementCounter,
        tooltip: 'Increment',
        child: Icon(Icons.add),
      ),
    );
  }
}
```

```
import 'dart:async';
import 'dart:convert';

import 'package:flutter/material.dart';
import 'package:flutter/services.dart' show ByteData, rootBundle;

class Translations {
  Translations(this.locale) {
    _localizedValues = null;
  }

  Locale locale;
  static Map<dynamic, dynamic> _localizedValues;

  static Translations of(BuildContext context) {
    return Localizations.of<Translations>(context, Translations);
  }

  String text(String key) {
    return _localizedValues[key] ?? '** $key not found';
  }

  static Future<Translations> load(Locale locale) async {
    Map<dynamic, dynamic> packageLocalizeValues;
    packageLocalizeValues = await _getPackageLocaleJson();

    Translations translations = Translations(locale);
    _localizedValues ??= {};

    _localizedValues.addAll(packageLocalizeValues);

    return translations;
  }

  static Future<Map<dynamic, dynamic>> _getPackageLocaleJson() async {
    Map<dynamic, dynamic> packageLocalizeValues = {};
    try {
      // workaround
      // final ByteData data = await rootBundle.load("locale/i18n_en_US.json");
      // String localeJson = utf8.decode(data.buffer.asUint8List());
      String localeJson = await rootBundle.loadString("locale/i18n_en_US.json");
      try {
        packageLocalizeValues = json.decode(localeJson);
      } catch (e) {
        print("Invaid locale json");
        return null;
      }
    } catch (ex) {
      print('Could not find assets.');
      return null;
    }
    print('All success!');
    return packageLocalizeValues;
  }

  String get currentLanguage => locale.languageCode;
}

class TranslationsDelegate extends LocalizationsDelegate<Translations> {
  TranslationsDelegate();

  @override
  bool isSupported(Locale locale) => true;

  @override
  Future<Translations> load(Locale locale) {
    return Translations.load(locale);
  }

  @override
  bool shouldReload(TranslationsDelegate old) => false;
}
```

```
import 'package:flutter_driver/driver_extension.dart';
import 'package:json_test/main.dart' as app;

void main() {
  enableFlutterDriverExtension();

  app.main();
}
```

```
import 'package:flutter_driver/flutter_driver.dart';
import 'package:test/test.dart';

void main() {
  FlutterDriver driver;

  Future<void> tapAndPrint(String finder) async {
    await driver.tap(find.byValueKey(finder));
    print('Performed action on $finder');
  }

  setUpAll(() async {
    driver = await FlutterDriver.connect();
    print('Driver started');
  });

  test('Check flutter driver health', () async {
    Health health = await driver.checkHealth();
    print(health.status);
  });

  test('Increment', () async {
    await tapAndPrint('increment_key');
  });
}
```