Flutter Shared Preferences And Settings Menu Demo
While Android/Java is super easy to use Shared Preferences, Flutter/Dart's Shared_Preferences is not that straightforward.
When I was learning Shared Preferences, I did a lot of Google searching. Most of what I found is talking about making separate class file or creating tons of setter/getter functions. I was wondering if I can code it differently. So I tried my own simply way.
Here is what I did.
First add dependency to file pubspec.yaml.
dependencies:
flutter:
sdk: flutter
# The following adds the Cupertino Icons font to your application.
# Use with the CupertinoIcons class for iOS style icons.
cupertino_icons: ^0.1.3
# TODO: Add dependency
shared_preferences: ^0.5.10
And "Pub Get" it.
Then import package.
import 'package:flutter/material.dart';
//TODO: import package
import 'package:shared_preferences/shared_preferences.dart';
Three Steps To Use SharedPreferences In Flutter/Dart
1. Initialization
The key to use Flutter SharedPreferences is to initialize it in the async main() and declare a top-level variable before main(). So we can use it any time after.
SharedPreferences mSharedPreferences;
void main() async {
WidgetsFlutterBinding.ensureInitialized(); //must include this line.
mSharedPreferences = await SharedPreferences.getInstance();
runApp(MyApp());
}
In this demo, we'll display a temperature reading, in user preferred temperature unit, either Celsius or Fahrenheit, which is stored in Shared_Preferences. The data we got from API could be in C or F. A conversion must be done before we can display the information.
Then we have a settings menu, letting user choose between C and F. When you tap on a letter, C or F, its color changes to active yellow. The other one changes to grey. And the value is saved to Shared Preferences. Meanwhile the homepage temperature number and unit are also changed accordingly.
The demo runs like this.
2. Get Value From Shared_Preferences
Every time we start the app, we check the value from SharedPreferrences. If not set(first time running), we set it to default, which is "C".
var key1='MyUnit';
var preferredUnit;
@override
void initState() {
super.initState();
preferredUnit = mSharedPreferences.getString(key1) ?? 'C';
}
You can .getString() any KEY without declaring or initializing it. You can create multiple Shared_Preferences, such as
var x = mSharedPreferences.getString(key2);
var x = mSharedPreferences.getInt('key3');
var x = mSharedPreferences.getBool('AnyKey');
You can check if the key-value pair exists by:
if (mSharedPreferences.getString('KEY')==null) {}
if (mSharedPreferences.getInt('KEY')==null) {}
Before its value is set, any SharedPreferences value is null.
3. Save Value to Shared_Preferences
After user taps to change preferred unit, we need to save that value to SharedPreferences.
//if user taps on 'F'
mSharedPreferences.setString(key1, 'F');
Just like the getter, you can save value to multiple Shared Preferences without declaring.mSharedPreferences.setString(key1, 'F');
//Don't do this right after:
preferredUnit = mSharedPreferences.getString(key1);
//in stead, do this:
preferredUnit = 'F';
Flutter/Dart Settings Menu
Flutter/Dart doesn't have predefined Settings Menu. You can import some packages, such as https://pub.dev/packages/shared_preferences_settings.
Or you can just DIY, like what I did in this demo.
The complete main.dart file is listed below. Hope you enjoy it.
main.dart
import 'package:flutter/material.dart';
//TODO: import package
import 'package:shared_preferences/shared_preferences.dart';
SharedPreferences mSharedPreferences;
void main() async {
WidgetsFlutterBinding.ensureInitialized(); // must include this line
mSharedPreferences = await SharedPreferences.getInstance();
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
final key1 = 'MyUnit'; // KEY for Shared_Preferences
final apiTemperature = 20; // usually we get these data from API,
final apiUnit = 'C'; // unit could be C or F,
var preferredUnit; // so we have to convert it first to match user preferred unit.
@override
void initState() {
super.initState();
// This is how to initialize a Key-Value pair of SharedPreferences.
// it's value is always null before we set a value to it.
preferredUnit = mSharedPreferences.getString(key1) ?? 'C';
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
actions: <Widget>[
PopupMenuButton(
color: Colors.greenAccent,
icon: Icon(Icons.settings),
itemBuilder: (context) => [
PopupMenuItem(
value: 1,
child: StatefulBuilder(
//important: make MenuItem Stateful, so it can change color when tapped
builder: (BuildContext context, StateSetter setState) {
return Row(
children: <Widget>[
Column(
children: [
Text('Choose a unit'),
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
InkWell(
onTap: () {
if (preferredUnit == 'F') {
//This is how we save a value to SharedPreferences,
//it's kind of async operation,
// MIGHT take a while to finish,
mSharedPreferences.setString(key1, 'C');
setState(() {
//so we assign the value directly without touching SharedPreferences
preferredUnit = 'C';
});
//the MenuItem is now inside StatefulBuilder
//we have to make anther setState inside MyHomePage
mySetState('C');
}
},
child: Container(
color: (preferredUnit == 'C')
? Colors.yellowAccent
: Colors.black12,
child: Text('°C'),
),
),
Container(
child: Text(' '),
),
InkWell(
onTap: () {
if (preferredUnit == 'C') {
mSharedPreferences.setString(key1, 'F');
setState(() {
preferredUnit = 'F';
});
mySetState('F');
}
},
child: Container(
color: (preferredUnit == 'C')
? Colors.black12
: Colors.yellowAccent,
child: Text('°F '),
),
),
],
),
],
),
],
);
}),
),
PopupMenuItem(
// a blank menu item
child: Text("About"),
value: 2,
),
],
onSelected: (result) {
if (result == 2) {}
},
),
],
title: Text('Flutter Demo'),
),
body: Center(
child: Row(
children: <Widget>[
Text(' Today\'s temperature: '),
Text(
CFConverter(apiTemperature, apiUnit).toString(),
style: TextStyle(fontSize: 40, color: Colors.redAccent),
),
Text(
'°' + preferredUnit,
style: TextStyle(fontSize: 40, color: Colors.deepOrangeAccent),
),
],
),
),
);
} //Widget builder end
void mySetState(String unit) {
setState(() {
preferredUnit = unit;
});
}
int CFConverter(int temperature, String unit) {
if (preferredUnit == apiUnit) {
return temperature;
} else if (apiUnit != '' && preferredUnit != apiUnit) {
if (apiUnit == 'C') {
return (temperature * 1.8 + 32).round();
} else if (apiUnit == 'F') {
return ((temperature - 32) / 1.8).round();
}
}
}
}
Comments
Post a Comment