Newby Coder header banner

Flutter Shared Preferences

Shared Preferences are used to save and retrieve data of basic data types like integer, float, boolean, string etc, in the form of key-value pairs

shared_preferences package can be used to store simple data like bool, String, double, int as key-value pairs where a key is of type String


Creating new Flutter App

Check Flutter installation to setup Flutter

Use flutter create command to create a Flutter project (here local_storage_app :

flutter create local_storage_app

Dependency

Implementation

Import
import 'package:shared_preferences/shared_preferences.dart';

Get instance of SharedPreferences

Future<SharedPreferences> _prefs = SharedPreferences.getInstance();

Getting and setting values

// to get value of a preference variable 'counter'
final int counter = (prefs.getInt('counter') ?? 0) + 1;

App Code

The home screen widget renders a TabBar whose selected index is stored to persist over restarts (check app with state persistence)

Shared preferences storage is implemented below in SharedPreferencesWidget

import 'dart:async';

import 'package:flutter/material.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:state_persistence/state_persistence.dart';


void main() => runApp(PersistentStorageApp());

class PersistentStorageApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return PersistedAppState(
      storage: JsonFileStorage(initialData: {
        'tab': 1,
        'imageCacheFilename': '',
      }),
      child: MaterialApp(
        title: 'Persistent Storage Example App',
        theme: ThemeData(primarySwatch: Colors.blue),
        home: EgWidget(),
      ),
    );
  }
}

class EgWidget extends StatefulWidget {
  @override
  _EgWidgetState createState() => _EgWidgetState();
}

class _EgWidgetState extends State<EgWidget> with SingleTickerProviderStateMixin {
  PersistedData _data;
  TabController _controller;

  @override
  void didChangeDependencies() {
    super.didChangeDependencies();
    _data = PersistedAppState.of(context);
    if (_data != null && _controller == null) {
      print("init controller");
      _controller = TabController(initialIndex: _data['tab'] ?? 0, vsync: this, length: 4);
      _controller.addListener(_onTabChanged);
    }
  }

  void _onTabChanged() {
    if (!_controller.indexIsChanging) {
      _data['tab'] = _controller.index;
    }
  }

  @override
  void dispose() {
    _controller?.removeListener(_onTabChanged);
    _controller?.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    if (_data != null) {
      return Scaffold(
        appBar: AppBar(
          title: Text('Persistent Tab Example'),
          bottom: TabBar(
            controller: _controller,
            tabs: [
              Tab(text: 'Tab 1'),
              Tab(text: 'Shared Preference'),
              Tab(text: 'Json Storage'),
              Tab(text: 'Cache Storage'),
            ],
          ),
        ),
        body: TabBarView(
          controller: _controller,
          children: [
            Container(color: Colors.cyanAccent[400], child: Center(child: Text('Tab 1', style: TextStyle(fontWeight: FontWeight.bold, color: Colors.white)))),
            SharedPreferencesWidget(),
            Container(color: Colors.greenAccent[700], child: Center(child: Text('Tab 3', style: TextStyle(fontWeight: FontWeight.bold, color: Colors.white)))),
            Container(color: Colors.brown[900], child: Center(child: Text('Tab 1', style: TextStyle(fontWeight: FontWeight.bold, color: Colors.white)))),
          ],
        )
      );
    }
    else {
      return Center(child: CircularProgressIndicator());
    }
  }
}

class SharedPreferencesWidget extends StatefulWidget {
  SharedPreferencesWidget({Key key}) : super(key: key);

  @override
  SharedPreferencesWidgetState createState() => SharedPreferencesWidgetState();
}

class SharedPreferencesWidgetState extends State<SharedPreferencesWidget> {
  Future<SharedPreferences> _prefs = SharedPreferences.getInstance();
  Future<int> _counter;

  Future<void> _incrementCounter() async {
    final SharedPreferences prefs = await _prefs;
    final int counter = (prefs.getInt('counter') ?? 0) + 1;
    setState(() {
      _counter = prefs.setInt("counter", counter).then((bool success) {
        return counter;
      });
    });
  }

  @override
  void initState() {
    super.initState();
    _counter = _prefs.then((SharedPreferences prefs) {
      return (prefs.getInt('counter') ?? 0);
    });
  }

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

Run instructions

Ensure a supported device is connected or emulator/simulator is started

Go to project directory

Use flutter run command to run

flutter run

It builds and runs app on an available android/ios device


Screenshot/image

Android

cl-flutter-local-storage-shared-preferences

iOS

cm_flutter_shared_preferences_as1cm_flutter_shared_preferences_as2cm_flutter_shared_preferences_as3
cm_flutter_shared_preferences_as4cm_flutter_shared_preferences_as5