Flutter Offline caching

After call rest api, you need to cache it on local for offline use.

Let’s begin!

About caching implementation please look at: https://pub.dev/packages/bflutter/versions/0.1.2

Install bflutter by add to pubspec.yaml 

dependencies:
  bflutter: 

Create a net_cache model for unifying model from local and network

/// Cache data from the Network model
class NetCache<T> {
  final T data;
  final dynamic error;
  bool fromNet = false;

  bool get hasData => data != null;
  bool get hasError => error != null;

  NetCache({bool fromNet, this.data, this.error}) {
    if (fromNet != null) this.fromNet = fromNet;
  }
}

Flow fetching data

The user makes a request action to get data, I use Observable.merge for this case. It will merge 2 streams from the network and from local storage, which one comes first then show it first, but remember the cached data just for display only, and the data from the network is final.

// @nhancv 10/7/2019: Combine with cache data
return Observable<NetCache<List<User>>>.merge([
  // Get data from api
  Observable.fromFuture(Api().searchUsers(input))
      .asyncMap((data) async {
    print('From net: $data');
    if (data == null) {
      return NetCache(fromNet: true, data: <User>[]);
    }
    if (data.statusCode == 200) {
      final List<User> result = json
          .decode(data.body)['items']
          .cast<Map<String, dynamic>>()
          .map<User>((item) => User.fromJson(item))
          .toList();
      // @nhancv 10/7/2019: Storage data from network to local
      await BCache().insert(Piece(id: input, body: data.body));


      // @nhancv 10/7/2019: Return latest data from network
      return NetCache(fromNet: true, data: result);
    } else {
      throw (data.body);
    }
  }).handleError((error) {}),
  // Get data from local storage
  Observable.fromFuture(BCache().queryById(input)).map((data) {
    print('From cache: $data');
    if (data == null) {
      return NetCache(data: <User>[]);
    }
    List<User> result = json
        .decode(data.body)['items']
        .cast<Map<String, dynamic>>()
        .map<User>((item) => User.fromJson(item))
        .toList();
    return NetCache(data: result);
  })
]);

Source: https://github.com/beesightsoft/bflutter

Leave a Reply

Your email address will not be published.Required fields are marked *