Flutter/Dart Shared Preferences和设置菜单实例
在 Android Studio/Java 里,Shared Preferences 很容易使用。而在 Flutter/Dart 里,Shared_Preferences就比较让人捉摸不透。
我刚开始学 Shared Preferences 时,我搜索了很多资料。大部分都是讲要创建一个另外的 Class file,或者建立很多很多的 setter/getter 函数。我在想我能不能用另外一种更简单的方法呢。
下面就介绍一下我是怎么做的。
首先向文件 pubspec.yaml 添加 dependency:
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: 这里添加
shared_preferences: ^0.5.10
然后点 "Pub Get" :
然后 import package:
import 'package:flutter/material.dart';
//TODO: 添加 package
import 'package:shared_preferences/shared_preferences.dart';
Flutter/Dart 使用 SharedPreferences 3步骤
1. 初始化
使用 SharedPreferences 的关键就是在 async main() 里创建一个实例,然后在 main() 之前定义一个最高级别变量。之后我们就可以随时随地使用它了。
SharedPreferences mSharedPreferences;
void main() async {
WidgetsFlutterBinding.ensureInitialized(); //这一行必须有
mSharedPreferences = await SharedPreferences.getInstance();
runApp(MyApp());
}
在这个演示应用中,我们会展示一个气温读数。这个读数的单位是用户选定的,可以是摄氏度C或华氏度F。这个用户偏好就储存在 Shared_Preferences 中。 通常这些数据我们从 API 获得,单位可能是 C ,也可能是 F 。所以展示之前必须转换单位到用户偏好的单位。
接着就是一个设置菜单,用户从这里选择自己要的单位 C 或 F 。这里有两个单位 C 和 F 供选择。你按其中一个字母,那个字母就变成黄色,表示已被选择,同时另一个字母就变为灰色。紧接着就要把这个新选择的值保存到 Shared Preferences,同时主页上的气温数据和单位都要相应变更。
这是整个应用运行的演示图:
2. 从 Shared_Preferences 获取数据
每次这个应用开始运行时都会从 SharedPreferrences 读一下用户设定的单位值。如果没有这个值(因为第一次运行),我们就设它为缺省值 "C"。
var key1='MyUnit';
var preferredUnit;
@override
void initState() {
super.initState();
preferredUnit = mSharedPreferences.getString(key1) ?? 'C';
}
你不用声明或初始化,你就可以去读取任意 KEY 对应的值。你可以读取(并创建)任意多的 KEY-Value Pair 。例如:
var x = mSharedPreferences.getString(key2);
var x = mSharedPreferences.getInt('key3');
var x = mSharedPreferences.getBool('AnyKey');
当然,如果一个 KEY-Value Pair 从没有创建过,它对应的值是 null 。我们可以这样检查有没有这个 KEY-Value Pair :
if (mSharedPreferences.getString('KEY')==null) {}if (mSharedPreferences.getInt('KEY')==null) {}
3. 保存值到 Shared_Preferences
用户选取新的温度单位后,我们要把这个值保存到 SharedPreferences 。
//如果用户按了F
mSharedPreferences.setString(key1, 'F');
就像读取值时一样,保存值到 Shared Preferences 也不用初始化。但这个保存的操作是一种 "async" 异步操作,有可能不会同步完成。所以如果你马上要用这个值,不要从 Shared Preferences 获取,而是把这个值直接赋给一个变量。 mSharedPreferences.setString(key1, 'F');
//不用马上这样操作:
preferredUnit = mSharedPreferences.getString(key1);
//而是这样做:
preferredUnit = 'F';
Flutter/Dart 设置菜单
Flutter/Dart 没有现成的设置菜单。你可以引入一些 packages ,比如:
https://pub.dev/packages/shared_preferences_settings
或者你自己动手,像我这里做的一样。
下面是 main.dart 文件的全部代码,希望你喜欢。
main.dart
import 'package:flutter/material.dart'; //TODO: 引入 package import 'package:shared_preferences/shared_preferences.dart'; SharedPreferences mSharedPreferences; void main() async { WidgetsFlutterBinding.ensureInitialized(); // 必须有这一行 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'; // Shared_Preferences 的 Key final apiTemperature = 20; // 通常从 API 获得这些数据 final apiUnit = 'C'; // API 的单位可能是 C 也可能是 F, var preferredUnit; // 读取用户偏好单位 @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:所以要先转换到我们想要的单位值 [ PopupMenuButton( color: Colors.greenAccent, icon: Icon(Icons.settings), itemBuilder: (context) => [ PopupMenuItem( value: 1, child: StatefulBuilder( //注意:这是把 MenuItem 变成 Stateful, //它才可以被按后变颜色 builder: (BuildContext context, StateSetter setState) { return Row( children: [ Column( children: [ Text('Choose a unit'), Row( mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [ InkWell( onTap: () { if (preferredUnit == 'F') { //保存值到 SharedPreferences, //它是一个 async 异步操作, // 可能不会同步完成, mSharedPreferences.setString(key1, 'C'); setState(() { //所以我们直接把C赋给 preferredUnit //而不是从 SharedPreferences 获得 preferredUnit = 'C'; }); //MenuItem 现在在 StatefulBuilder 里面 //所以必须在MyHomePage里再做一个setState来刷新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: [ 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(); } } } }

评论
发表评论