Search code examples
dartflutterdart-async

How to read local file when there is no internet connection on flutter?


I've implemented a ListView that loads a Json from internet. So far so good. But I'd like to read a local file in case that attempt to read the online json fails.

I have an async method that reads either a json from internet or from a local asset:

Future<List<Post>> getPosts(String urlJsonInternet, String fileJsonLocal) async {

  //read json from internet
  await http.get(urlJsonInternet).then((responseInternet) {

      //If server returns an OK response, parse the JSON
      return _buildPostList(responseInternet.body);

  }).catchError((onError) {

     //read json from local file
     rootBundle.loadString(fileJsonLocal).then((responseLocal) {
        return _buildPostList(responseLocal);
     });

  });

}

_buildPostList it's just a method that parses the json.

To test it I turned off the network at the Android Emulator.

What is happening is that nothing is returned to the Snapshot at FutureBuilder. It seems like something related to the execution order of the process.

This is the screenshot of the exception: https://ibb.co/iMSRsJ


Solution

  • You are making wrong use of asnyc await and promises. When using await, you should not use then because they do exactly the same. Check this out for reference on Future's.

    You are also returning from the wrong scope, i.e. both of your return's return to the callbacks and not to your function getPosts. I will rewrite getPosts with async await and try catch.

    Lines after await only get executed once the Future is finished. More on that here.

    Future<List<Post>> getPosts(String urlJsonInternet, String fileJsonLocal) async {
      try {
        //read json from internet
        final responseInternet = await http.get(urlJsonInternet);
    
        //If server returns an OK response, parse the JSON
        return _buildPostList(responseInternet.body);
      } catch (e) {
        //read json from local file
        final responseLocal = await rootBundle.loadString(fileJsonLocal);
    
        return _buildPostList(responseLocal);
      }
    }