// Copyright 2013 The Flutter Authors // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // ignore_for_file: public_member_api_docs import 'dart:async'; import 'package:flutter/material.dart'; import 'package:shared_preferences/shared_preferences.dart'; // #docregion migrate import 'package:shared_preferences/util/legacy_to_async_migration_util.dart'; // #enddocregion migrate void main() { runApp(const MyApp()); } class MyApp extends StatelessWidget { const MyApp({super.key}); @override Widget build(BuildContext context) { return const MaterialApp( title: 'SharedPreferencesWithCache Demo', home: SharedPreferencesDemo(), ); } } class SharedPreferencesDemo extends StatefulWidget { const SharedPreferencesDemo({super.key}); @override SharedPreferencesDemoState createState() => SharedPreferencesDemoState(); } class SharedPreferencesDemoState extends State { final Future _prefs = SharedPreferencesWithCache.create( cacheOptions: const SharedPreferencesWithCacheOptions( // This cache will only accept the key 'counter'. allowList: {'counter'}, ), ); late Future _counter; int _externalCounter = 0; /// Completes when the preferences have been initialized, which happens after /// legacy preferences have been migrated. final Completer _preferencesReady = Completer(); Future _incrementCounter() async { final SharedPreferencesWithCache prefs = await _prefs; final int counter = (prefs.getInt('counter') ?? 0) + 1; setState(() { _counter = prefs.setInt('counter', counter).then((_) { return counter; }); }); } /// Gets external button presses that could occur in another instance, thread, /// or via some native system. Future _getExternalCounter() async { final prefs = SharedPreferencesAsync(); final int externalCounter = (await prefs.getInt('externalCounter')) ?? 0; setState(() { _externalCounter = externalCounter; }); } Future _migratePreferences() async { // #docregion migrate const sharedPreferencesOptions = SharedPreferencesOptions(); final SharedPreferences prefs = await SharedPreferences.getInstance(); await migrateLegacySharedPreferencesToSharedPreferencesAsyncIfNecessary( legacySharedPreferencesInstance: prefs, sharedPreferencesAsyncOptions: sharedPreferencesOptions, migrationCompletedKey: 'migrationCompleted', ); // #enddocregion migrate } @override void initState() { super.initState(); _migratePreferences().then((_) { _counter = _prefs.then((SharedPreferencesWithCache prefs) { return prefs.getInt('counter') ?? 0; }); _getExternalCounter(); _preferencesReady.complete(); }); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: const Text('SharedPreferencesWithCache Demo')), body: Center( child: _WaitForInitialization( initialized: _preferencesReady.future, builder: (BuildContext context) => FutureBuilder( future: _counter, builder: (BuildContext context, AsyncSnapshot snapshot) { switch (snapshot.connectionState) { case ConnectionState.none: case ConnectionState.waiting: return const CircularProgressIndicator(); case ConnectionState.active: case ConnectionState.done: if (snapshot.hasError) { return Text('Error: ${snapshot.error}'); } else { return Text( 'Button tapped ${snapshot.data ?? 0 + _externalCounter} time${(snapshot.data ?? 0 + _externalCounter) == 1 ? '' : 's'}.\n\n' 'This should persist across restarts.', ); } } }, ), ), ), floatingActionButton: FloatingActionButton( onPressed: _incrementCounter, tooltip: 'Increment', child: const Icon(Icons.add), ), ); } } /// Waits for the [initialized] future to complete before rendering [builder]. class _WaitForInitialization extends StatelessWidget { const _WaitForInitialization({ required this.initialized, required this.builder, }); final Future initialized; final WidgetBuilder builder; @override Widget build(BuildContext context) { return FutureBuilder( future: initialized, builder: (BuildContext context, AsyncSnapshot snapshot) { if (snapshot.connectionState == ConnectionState.waiting || snapshot.connectionState == ConnectionState.none) { return const CircularProgressIndicator(); } return builder(context); }, ); } }