provider_assist 1.5.1

  • Readme
  • Changelog
  • Example
  • Installing
  • 80

Provider Assist #

This is a simple package used to enhance the provider package with additional features for Flutter and a standard MVVM pattern. It is still very early and is still open to suggestions.

Note: This pattern is very heavily influenced by FilledStacks Provider v3 Architecture (Thanks a lot!)

In a nutshell #

This package wraps your top level views for each page in BaseView, this widget should pass in a model which extends BaseViewModel. Once you have wrapped your view, this package will give you callbacks and metadata during build which can be used to enhance the quality of your code.

Breaking Change (1.5.0) #

The onViewFirstLoad, onEventReceived, and onErrorReceived callback will now supply the model. Please update your code to include this additional parameter. Apologies for this, this was an oversight on me but it will allow you to interact with your model immediately after the view is visible. This is useful for a number of things, e.g. checking if the user is logged in on a splash view.

Lifecycle #

Lifecycle

Features #

  1. Provide layout information on the builder of the view, this will include:
    1. Whether the device is a tablet or not (7" or above)
    2. Whether the device is landscape
  2. Provide raising and handling of errors in your view model by implementing the onErrorOccured callback.
    1. Call notifyError in your ViewModel, passing it a error code as a string
    2. Implement the onErrorOccured function on your view to get the error code passed by the view model and act on it
  3. Callbacks for onModelReady and onViewReady
    1. onModelReady will be run once when the models constructor has completed
    2. onViewReady will be run once when the view first renders to the screen
  4. Basic translation and localization support
    1. You have to import the flutter localizations package in your pubspec, see the example
    2. Next call registerTranslations() from your main method, passing in a map of locales to key/value pairs
    3. The translations will then be passed down for your locale in the layoutInformation property in baseView
  5. Generic event callback from ViewModel to View via notifyEvent and onEventOccured
    1. Call notifyEvent in your ViewModel, passing it a string representing the event
    2. Implement the onEventOccured function on your view to get the event passed by the view model and act on it
    3. This can be useful for telling the UI to navigate, for example when a user logins in

Future Features #

This is down to you! I use this on a daily basis so I will be adding features I find useful in everyday development. For example:

  1. Improve Localization
  2. Globally handling errors rather than implementing on each view (for example pushing an error page)
  3. Passing further data down to the widget about the system. OS, etc...

TODO #

  • Write tests to improve rating
  • Improve documentation and example

Example Main #

void main() {
  registerTranslations(translations);
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Example',
      // Swap below to change locale
      locale: Locale('en'),
      // locale: Locale('hi'),
      supportedLocales: <Locale>[
        Locale('en'),
        Locale('hi'),
      ],
      localizationsDelegates: <LocalizationsDelegate>[
        GlobalMaterialLocalizations.delegate,
        GlobalWidgetsLocalizations.delegate,
      ],
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: View(),
    );
  }
}

Map<Locale, Map<String, String>> translations = {
  Locale('en'): {
    'view_title': 'Example Title',
    'view_raise_error': 'Raise Error',
    'view_raise_event': 'Raise Event',
  },
  Locale('hi'): {
    'view_title': 'उदाहरण शीर्षक',
    'view_raise_error': 'त्रुटि उठाएँ',
    'view_raise_event': 'घटना को बढ़ाएँ',
  },
};

Example View #

class View extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return BaseView<ViewModel>(
      model: ViewModel(),
      onErrorOccured: (BuildContext context, String errorCode) {
        print("Got a new error: $errorCode");
      },
      onEventOccured: (BuildContext context, String event) {
        print("Got a new event: $event");
      },
      onModelReady: (ViewModel model) {
        print("Model is ready, but view is still not visible");
      },
      onViewFirstLoad: (BuildContext context, ViewModel model) {
        print("View is rendered");
      },
      builder: (BuildContext context, ViewModel vm, LayoutInformation layout) {
        print("Device type: ${layout.deviceType}");
        print("Device orientation: ${layout.orientation}");
        return Scaffold(
          backgroundColor: layout.theme.backgroundColor,
          appBar: AppBar(
            title: Text(layout.translations['view_title']),
          ),
          body: Container(
            width: double.infinity,
            alignment: Alignment.center,
            child: Column(
              mainAxisAlignment: MainAxisAlignment.center,
              children: <Widget>[
                CupertinoButton(
                  child: Text(layout.translations['view_raise_error']),
                  onPressed: () => vm.onErrorRequested(),
                ),
                SizedBox(height: 8.0),
                CupertinoButton(
                  child: Text(layout.translations['view_raise_event']),
                  onPressed: () => vm.onEventRequested(),
                ),
              ],
            ),
          ),
        );
      },
    );
  }
}

Example View Model #

class ViewModel extends BaseViewModel {
  void onErrorRequested() {
    try {
      setBusy(true);
      notifyError('Random error');
    } finally {
      setBusy(false);
    }
  }

  void onEventRequested() {
    try {
      setBusy(true);
      notifyEvent('Random event');
    } finally {
      setBusy(false);
    }
  }
}

[1.5.1] - 17/09/2019

  • Improve Documentation

[1.5.0] - 17/09/2019

  • BREAKING CHANGE: onEventReceived and onErrorReceived will now supply the model. You will need to ammend your code to include this!

[1.4.1] - 20/09/2019

  • Provide the current context of the consumer in layoutInformation, use this sparingly!

[1.4.0] - 17/09/2019

  • BREAKING CHANGE: onViewFirstLoad will now supply the model. You will need to ammend your code to include this!

[1.3.2] - 17/09/2019

  • Fix another small bug with event streams.

[1.3.1] - 17/09/2019

  • Fix a bug where the same stream was being listened to twice causing an assertion.

[1.3.0] - 16/09/2019

  • Added a new callback on BaseViewModel to raise events back to the UI via a string, this can be used for anything. Examples being login, navigation requests, etc.

[1.2.0] - 13/09/2019

  • Basic localization support, see example

[1.1.0] - 10/09/2019

  • (BREAKING CHANGES) Refactored the LayoutInformation passed back from the build function to be more futureproof.

[1.0.0] - 10/09/2019

  • Leverage locale in layout information, first stable release

[0.0.2] - 09/09/2019

  • Improve documentation around BaseView

[0.0.1] - 09/09/2019

  • Initial release with basic feature set

example/README.md

example #

A new Flutter project.

Getting Started #

This project is a starting point for a Flutter application.

A few resources to get you started if this is your first Flutter project:

For help getting started with Flutter, view our online documentation, which offers tutorials, samples, guidance on mobile development, and a full API reference.

Use this package as a library

1. Depend on it

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


dependencies:
  provider_assist: ^1.5.1

2. Install it

You can install packages from the command line:

with Flutter:


$ flutter pub get

Alternatively, your editor might support 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:provider_assist/provider_assist.dart';
  
Popularity:
Describes how popular the package is relative to other packages. [more]
61
Health:
Code health derived from static analysis. [more]
100
Maintenance:
Reflects how tidy and up-to-date the package is. [more]
100
Overall:
Weighted score of the above. [more]
80
Learn more about scoring.

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

  • Dart: 2.5.1
  • pana: 0.12.21
  • Flutter: 1.9.1+hotfix.4

Platforms

Detected platforms: Flutter

References Flutter, and has no conflicting libraries.

Dependencies

Package Constraint Resolved Available
Direct dependencies
Dart SDK >=2.1.0 <3.0.0
flutter 0.0.0
flutter_localizations 0.0.0
provider ^3.1.0 3.1.0+1
Transitive dependencies
collection 1.14.11 1.14.12
intl 0.15.8 0.16.0
meta 1.1.7
path 1.6.4
sky_engine 0.0.99
typed_data 1.1.6
vector_math 2.0.8
Dev dependencies
flutter_test