prefs 3.0.0

Store and Read Your App’s Preferences #

A Flutter Example #

What’s Your Preference? #

The plugin, shared_preferences, is offered to Flutter developers to store and read their app’s preferences in both the Android and the iOS platform. It wraps the NSUserDefaults (on iOS) and the SharedPreferences (on Android), providing persistent storage. Note, as of this writing, the plugin does not guarantee its writes to disk and suggests it not be used for storing critical data. As it is, it’s worked for me so far. So much so, I’ve adapted it fully for my apps.

Prefs Logo

There’s a Class for That #

There’s an example provided by the plugin website demonstrating how the plugin is implemented. In my opinion, not the most realistic example as it just promptly displays an integer demonstrating the success of its persistent storage. Regardless, I will use this same example now in this article to further demonstrate the use of a class library called, prefs.dart, that I freely offer to other developers to quickly and easily implement stored preferences in their app’s.

Take Five #

Below is the main.dart file that is very much like the example found in the plugin website. However, this file instead uses the class library, prefs.dart, to do much of the ‘heavy lifting’ behind the scenes when it comes to using the plugin. As a result, there are five lines in all required to implement and to demonstrate the app’s preferences storage and retrieval capabilities.

Take Five

What’s Going On Here #

After looking over the code above, there are a few things you will have noticed regarding the implementation of the class library. It’s all static function calls for one. Nothing is instantiated. You’d guess right, if you then deduced this is a static class. You won’t find any instance variables or instance methods in this class library. This allows you to more easily implement your app’s preferences anywhere in your app. Preferences are an important concern for your app, and so you should be able to reference them any time and any where in your app.

The only real requirements is that you first initialize the class library in the State object’s initState() function, and that you then clean up things in the State object’s dispose() function. After that, you are then free to call up preferences any time; any where they’re needed in your app.

Therefore, in this example, you see a call to static class function, Prefs.init(), to initialize, as it happens, a reference to the plugin, shared_preferences, in the State object’s initState() function. Correspondingly, you see a call to static class function, Prefs.dispose(), in the State object’s dispose() function to then clean things up when the app is terminated. Pretty straight forward. You don’t need to be concerned with what goes on this those functions — of course, being a free class library, you can readily go take a peek.

The Future is Now…or Not #

Like the original example in the plugin’s website, this example uses a Future object of type Future

Prefs Logo

In our example, the code does the very same thing, but it’s little cleaner:

Prefs Logo

It too returns a ‘Future’ object of type integer — a value of zero if the ‘counter’ key returns null. Returning null means there is no preference value with that key as of yet. Above, in the original code, you can determine a Future object is involved seeing that the callback function, then(), is being utilized. In our code, it’s the capital ‘F’ appended on the end of the function’s name that gives us the hint. Lastly, like the original code, the function, getIntF(), returns a non-null value of zero using the operator, ??, but you don’t readily need to know that. There’s more encapsulation involved here — keeping some of the operations behind the scenes.

In the original example, it takes two lines of code to increment the counter. A Future object of type integer can not be incremented like a numeric, and so we have ‘to wait’ for a ‘SharedPreferences’ object to be instantiated, then retrieve a value if any by the key, ‘counter’, and then increment the value by one:

incrementCounter

In our example, we’ve got it down to one short line of code:

new increment

Retrieving integer values from your app’s preferences is going to be a common operation. Best to write a function that repeatedly takes care of the details and, like the original code, supplies a value of zero if the provided key returns a null. You see the function doesn’t return a Future object but an integer. You can readily tell that by the declaration of the variable, counter, as well as by the missing capital ‘F.’

The State of the Counter #

Further on in the original example, the setState() function is called to ‘update’ the counter on the app’s screen:

original setState

In our example, you see the code does the very same thing, but this code doesn’t require the parent function, _incrementCounter(), to use the async keyword. There’s no await command being used. Nor does it reveal that it’s ‘SharedPerferences’ that’s the means for the persistent storage. Instead, you’re allowed to call this function any time; any where. Much cleaner and much easier to use.

new setState

As an aside, note the use of the ‘return’ statement allows you to assign, in this case, an integer value to the Future object, _counter. As you see, you can’t assign the integer value directly to a variable, _counter, of type Future

Future Error

You Get Ten #

You can see below all the ‘get’ functions available to the developer when using this class library. The first five returns the data type implied in each of the function’s names, while each then has their ‘Future’ counterpart in the remaining five functions.

Ten Gets

Here’s the Keys #

You’ve access to all the keys that can be found in your preferences. Like the ‘get’ functions, you have the option to return a ‘Future’ type of the set of Strings as well.

Get Keys

Let’s Get Dynamic #

If you like, you don’t have to be concerned with the ‘data type’ of the preference value and simply call the ‘get’ functions. Again, a ‘Future’ version is available.

Get Dynamic

It’s All Set Up #

Along with the first five ‘get’ functions there is a corresponding ‘set’ function. Each writes a particular data type to persistent storage. With a successful write, a Future data type of ‘bool’ is returned.

Set Functions

Remove and Clear #

You have a means to remove a specific preference and or clear out all the preferences with one command. They too return a Future of type, ‘bool.’

Remove Function

Conclusion #

There you have it. Take this class library, and use it for your app’s preferences. An extensive walkthrough the library package can be found in the Medium article, A Flutter Class for Your App’s Preferences.

3.0.0 #

Apr. 23, 2019

  • Breaking Change Make variable, instance, private with _instance to prevent possible memory leak.

2.1.0 #

Apr. 22, 2019

  • static Future

2.0.0 #

Apr. 22, 2019

  • New getter, prefs, for await SharedPreferences.getInstance();
  • getter allows for Hot Reload
  • Upgrade to shared_preferences 0.5.2

1.0.4 #

Mar. 16, 2019

  • Update the homepage field from pubspec.yaml

1.0.3 #

Mar. 15, 2019

  • sdk: '>=2.1.0 <3.0.0'

1.0.2 #

Feb. ‎28, 2019

  • Flutter format homepage: in pubspec.yaml

1.0.1 #

Feb. ‎28, 2019

  • Provide an example and a test

1.0.0 #

Feb. ‎27, 2019

  • ‎Initial Library Package Release

0.2.0 #

Feb. ‎09, ‎2019

  • static Future

0.1.1 #

Dec. ‎24, ‎2018

  • Update README.md

0.1.0 #

Nov. ‎24, ‎2018

  • Update README.md

0.0.1 #

June ‎2, ‎2018

  • Initial Release

example/main.dart

import 'dart:async' show Future;

import 'package:flutter/material.dart';

import 'package:prefs/prefs.dart';

void main() {
  runApp(new MyApp());
}

class MyApp extends StatelessWidget {
  // Define our test key
  final keyCounter = Key('counter');

  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      title: 'SharedPreferences Demo',
      home: new SharedPreferencesDemo(keyCount: keyCounter),
    );
  }
}

class SharedPreferencesDemo extends StatefulWidget {
  SharedPreferencesDemo({this.keyCount, Key key}) : super(key: key);
  final Key keyCount;
  @override
  SharedPreferencesDemoState createState() => new SharedPreferencesDemoState();
}

class SharedPreferencesDemoState extends State<SharedPreferencesDemo> {
  Future<int> _counter;

  void _incrementCounter() {
    final int counter = Prefs.getInt('counter') + 1;
    setState(() {
      _counter = Prefs.setInt('counter', counter).then((_) {
        return counter;
      });
    });
  }

  @override
  void initState() {
    super.initState();
    Prefs.init();
    _counter = Prefs.getIntF('counter');
  }

  @override
  void dispose() {
    Prefs.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      appBar: new AppBar(
        title: const Text("SharedPreferences Demo"),
      ),
      body: Center(
          child: new FutureBuilder<int>(
              future: _counter,
              builder: (BuildContext context, AsyncSnapshot<int> snapshot) {
                switch (snapshot.connectionState) {
                  case ConnectionState.waiting:
                    return const CircularProgressIndicator();
                  default:
                    if (snapshot.hasError)
                      return new Text('Error: ${snapshot.error}');
                    else
                      return new Text(
                        'Button tapped ${snapshot.data} time${snapshot.data == 1 ? '' : 's'}.\n\n'
                        'This should persist across restarts.',
                        key: widget.keyCount,
                      );
                }
              })),
      floatingActionButton: new FloatingActionButton(
        onPressed: _incrementCounter,
        tooltip: 'Increment',
        child: const Icon(Icons.add),
      ),
    );
  }
}

Use this package as a library

1. Depend on it

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


dependencies:
  prefs: ^3.0.0

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:prefs/prefs.dart';
  
Popularity:
Describes how popular the package is relative to other packages. [more]
78
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]
89
Learn more about scoring.

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

  • Dart: 2.4.0
  • pana: 0.12.19
  • Flutter: 1.7.8+hotfix.3

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
shared_preferences ^0.5.2 0.5.3+4
Transitive dependencies
collection 1.14.11
meta 1.1.6 1.1.7
sky_engine 0.0.99
typed_data 1.1.6
vector_math 2.0.8
Dev dependencies
flutter_test

Admin