async_resource 0.1.4

  • Readme
  • Changelog
  • Example
  • Installing
  • 82

async_resource #

Automatically cache network resources and use them when offline. Interface with local resources on any platform.

Examples #

See also the working example.

Wrapping in a stream #

// `res` is any AsyncResource.
final resource = StreamedResource(res);
resource.sink.add(false);

Flutter and native #

Import FileResource.

import 'package:async_resource/file_resource.dart';

Define a resource.

// Flutter needs a valid directory to write to.
// `getApplicationDocumentsDirectory()` is in the `path_provider` package.
// Native applications do not need this step.
final path = (await getApplicationDocumentsDirectory()).path;

final myDataResource = HttpNetworkResource<MyData>(
  url: 'https://example.com/my-data.json',
  parser: (contents) => MyData.fromJson(contents),
  cache: FileResource(File('$path/my-data.json')),
  maxAge: Duration(minutes: 60),
  strategy: CacheStrategy.cacheFirst,
);

Basic usage

final myData = await myDataResource.get();
// or without `await`
myDataResource.get().then((myData) => print(myData));

Flutter pull-to-refresh example

class MyDataView extends StatefulWidget {
  @override
  _MyDataViewState createState() => _MyDataViewState();
}

class _MyDataViewState extends State<MyDataView> {
  bool refreshing = false;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        body: RefreshIndicator(
            onRefresh: refresh,
            child: FutureBuilder<MyData>(
              future: myDataResource.get(forceReload: refreshing),
              initialData: myDataResource.data,
              builder: (context, snapshot) {
                if (snapshot.hasData) {
                  return _buildView(snapshot.data);
                } else if (snapshot.hasError) {
                  return Text('${snapshot.error}');
                }
                return Center(child: CircularProgressIndicator());
              },
            )));
  }

  Future<Null> refresh() async {
    setState(() => refreshing = true);
    refreshing = false;
  }
}

Flutter using Shared Preferences #

Import SharedPrefsResource.

import 'package:shared_prefs_resource/shared_prefs_resource.dart';

Definition

final themeResource = StringPrefsResource('theme');

Usage example

class ThemedApp extends StatefulWidget {
  @override
  State<StatefulWidget> createState() => _ThemedAppState();
}

class _ThemedAppState extends BlocState<ThemedApp> {
  @override
  Widget build(BuildContext context) {
    return FutureBuilder<MyData>(
        future: themeResource.get(),
        initialData: themeResource.data,
        builder: (context, snapshot) {
          if (snapshot.hasData) {
            return MaterialApp(
                title: 'My themed app',
                theme: buildTheme(snapshot.data),
                home: HomePage());
          } else if (snapshot.hasError) {
            return Text('${snapshot.error}');
          }
          return Center(child: CircularProgressIndicator());
        },
      );
  }
}

Web using service worker #

Import browser-based resources.

import 'package:async_resource/browser_resource.dart';

Define the resource.

final myDataResource = ServiceWorkerResource<MyData>(
    cache: ServiceWorkerCacheEntry(
        name: config.cacheName,
        url: 'https://example.com/my-data.json',
        parser: (contents) => MyData.fromJson(contents),
        maxAge: Duration(minutes: 60)));

Usage

myDataResource.get();

Web using local/session storage #

Import browser-based resources.

import 'package:async_resource/browser_resource.dart';

Define

final themeResource = StorageEntry('theme');
final sessionResource = StorageEntry('token', type: StorageType.sessionStorage);

Use

themeResource.get();
sessionResource.get();

[0.1.4] - November 25, 2018

  • Add data getter to StreamedResource.
  • Update deps

[0.1.3] - October 3, 2018

  • Add StreamedResource for wrapping an AsyncResource with a sink and stream.
  • Added a fully functional example that uses this package and async_resource_flutter.

[0.1.2] - August 25, 2018

  • Add examples to README.

[0.1.1] - August 25, 2018

  • Fix: catch platform layer errors (network/local) during fetchContents().

[0.1.0] - August 25, 2018

  • Fix ServiceWorkerCacheEntry. Bundled classes have undergone limited testing.

[0.0.5] - August 14, 2018

  • Add data getter and parser parameter to NetworkResource.

[0.0.4+1] - August 11, 2018

  • Warn if local resource does not exist 3 seconds after write.

[0.0.4] - August 11, 2018

  • Fix FileResource.lastModified to check for existence first.

[0.0.3] - August 7, 2018

  • Add delete method to local resources.
  • Minor fixes.

[0.0.2] - August 4, 2018

  • Fix library declarations.

[0.0.1] - August 3, 2018

  • First release.

example/example.dart

//
// Copy of https://github.com/jifalops/async_resource/blob/master/example/packages/base/lib/resources.dart
//

/// The resources required by mobile and web versions of the app.
///
/// This isn't really necessary to do, but it helps make sure mobile and web
/// versions of the app are consistent, and makes designing a bit easier.
abstract class Resources {
  Resources({@required this.posts, @required this.darkBackground});

  final LocalResource<bool> darkBackground;

  /// [AsyncResource]s use [Future]s by default, but they can be wrapped in a
  /// [StreamedResource] to access them using a sink and stream.
  final NetworkResource<Iterable<Post>> posts;
}

//
// Copy of https://github.com/jifalops/async_resource/blob/master/example/packages/mobile/lib/src/resources.dart
//

/// Shorthand for `MobileResources.instance`.
MobileResources get resources => MobileResources._instance;

class MobileResources extends Resources {
  MobileResources._(this.path)
      : super(
          posts: HttpNetworkResource<Iterable<Post>>(
            url: postsUrl,
            parser: (contents) => Post.fromJsonArray(contents),
            cache: FileResource(File('$path/posts.json')),
            maxAge: Duration(days: 30),
            strategy: CacheStrategy.cacheFirst,
          ),
          darkBackground: BoolPrefsResource('darkBackground'),
        );

  final String path;

  static MobileResources _instance;
  static MobileResources get instance => _instance;

  /// Do one-time initialization of [resources].
  static Future<MobileResources> init() async => _instance ??=
      MobileResources._((await getApplicationDocumentsDirectory()).path);
}

//
// Copy of https://github.com/jifalops/async_resource/blob/master/example/packages/web/lib/src/resources.dart
//

/// This can be created synchronously because it does not need to wait for a
/// file from the system like the mobile version does.
final resources = WebResources._();

class WebResources extends Resources {
  WebResources._()
      : super(
          posts: ServiceWorkerResource<Iterable<Post>>(
            strategy: CacheStrategy.cacheFirst,
            cache: ServiceWorkerCacheEntry(
              name: 'async_resource_example',
              url: postsUrl,
              parser: (contents) => Post.fromJsonArray(contents),
              maxAge: Duration(days: 30),
            ),
          ),
          darkBackground: StorageEntry<bool>('darkBackground',
              parser: (contents) => contents == 'true'),
        );
}

Use this package as a library

1. Depend on it

Add this to your package's pubspec.yaml file:


dependencies:
  async_resource: ^0.1.4

2. Install it

You can install packages from the command line:

with pub:


$ pub get

with Flutter:


$ flutter pub get

Alternatively, your editor might support pub get or flutter pub get. Check the docs for your editor to learn more.

3. Import it

Now in your Dart code, you can use:


import 'package:async_resource/async_resource.dart';
  
Popularity:
Describes how popular the package is relative to other packages. [more]
73
Health:
Code health derived from static analysis. [more]
91
Maintenance:
Reflects how tidy and up-to-date the package is. [more]
90
Overall:
Weighted score of the above. [more]
82
Learn more about scoring.

We analyzed this package on Nov 19, 2019, and provided a score, details, and suggestions below. Analysis was completed with status completed using:

  • Dart: 2.6.0
  • pana: 0.12.21

Platforms

Detected platforms: Flutter, web, other

No platform restriction found in primary library package:async_resource/async_resource.dart.

Health suggestions

Fix lib/async_resource.dart. (-3.93 points)

Analysis of lib/async_resource.dart reported 8 hints, including:

line 27 col 34: Use = to separate a named parameter from its default value.

line 38 col 23: Avoid empty catch blocks.

line 57 col 34: Use = to separate a named parameter from its default value.

line 98 col 5: Future results in async function bodies must be awaited or marked unawaited using package:pedantic.

line 100 col 13: DO use curly braces for all flow control structures.

Fix lib/browser_resource.dart. (-1.99 points)

Analysis of lib/browser_resource.dart reported 4 hints:

line 33 col 18: Use = to separate a named parameter from its default value.

line 87 col 5: Future results in async function bodies must be awaited or marked unawaited using package:pedantic.

line 105 col 17: Use = to separate a named parameter from its default value.

line 106 col 28: Use = to separate a named parameter from its default value.

Fix lib/file_resource.dart. (-1.99 points)

Analysis of lib/file_resource.dart reported 4 hints:

line 12 col 19: Use = to separate a named parameter from its default value.

line 13 col 20: Use = to separate a named parameter from its default value.

line 14 col 24: Use = to separate a named parameter from its default value.

line 43 col 5: Future results in async function bodies must be awaited or marked unawaited using package:pedantic.

Fix lib/src/http_network_resource.dart. (-1 points)

Analysis of lib/src/http_network_resource.dart reported 2 hints:

line 16 col 18: Use = to separate a named parameter from its default value.

line 17 col 29: Use = to separate a named parameter from its default value.

Maintenance issues and suggestions

Support latest dependencies. (-10 points)

The version constraint in pubspec.yaml does not support the latest published versions for 1 dependency (rxdart).

Dependencies

Package Constraint Resolved Available
Direct dependencies
Dart SDK >=2.0.0 <3.0.0
http ^0.12.0 0.12.0+2
meta ^1.0.0 1.1.8
path ^1.0.0 1.6.4
rxdart ^0.18.0 0.18.1 0.22.6
service_worker ^0.2.0 0.2.3
Transitive dependencies
async 2.4.0
charcode 1.1.2
collection 1.14.12
http_parser 3.1.3
js 0.6.1+1
pedantic 1.8.0+1
source_span 1.5.5
string_scanner 1.0.5
term_glyph 1.1.0
typed_data 1.1.6
Dev dependencies
mockito ^3.0.0
test ^1.0.0