[英]How to implement a process that uses flutter_secure_storage package to read and write the data [with Provider package]
I'm new to Flutter and Dart.我是 Flutter 和 Dart 的新手。 I made a simple Todos app with Provider package and Consumer.
我使用 Provider 包和 Consumer 制作了一个简单的 Todos 应用程序。 I'm trying to implement a process that uses flutter_secure_storage package to read and write the list data on the device.
我正在尝试实现一个过程,该过程使用 flutter_secure_storage 包在设备上读取和写入列表数据。 But I don't know how to implement it.
但我不知道如何实现它。
Checkbox widget requires a bool, while secure_storage requires the type of String.复选框小部件需要一个 bool,而 secure_storage 需要 String 类型。 Therefore, it is necessary to convert both types.
因此,有必要对这两种类型进行转换。 This also confuses me a little.
这也让我有点困惑。
The code is below.代码如下。 I would be happy if you could give me some advice.
如果你能给我一些建议,我会很高兴。
main.dart main.dart
// Todos app example
import 'package:consumer_samp/list_model.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
home: ChangeNotifierProvider<ListModel>(
create: (context) => ListModel(),
child: MyHomePage('Todos app example'),
),
);
}
}
class MyHomePage extends StatelessWidget {
MyHomePage(this.title);
final String title;
final TextEditingController eCtrl = TextEditingController();
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(title),
),
body: SingleChildScrollView(
child: Column(
children: <Widget>[
Container(
padding: EdgeInsets.all(10),
child: Row(
children: <Widget>[
Expanded(
child: TextField(
decoration: InputDecoration(
border: InputBorder.none,
hintText: 'Enter your ToDo item',
),
controller: eCtrl,
),
),
Consumer<ListModel>(
builder: (_, listModel, __) => FlatButton(
child: Text('Add'),
onPressed: () {
if (eCtrl.text != '') {
Map<String, dynamic> item = {
'value': false,
'text': eCtrl.text
};
listModel.addItem(item);
eCtrl.clear();
}
},
),
),
],
),
),
Center(
child: Consumer<ListModel>(builder: (_, listModel, __) {
var items = listModel.getItems;
return Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Container(
height: 300,
child: ListView.builder(
itemCount: items.length,
itemBuilder: (BuildContext context, int idx) =>
Container(
padding: const EdgeInsets.all(5),
color: Colors.green,
child: Row(
children: <Widget>[
Checkbox(
value: items[idx]['value'],
onChanged: (val) {
listModel.toggleValue(idx, val);
}),
Text(
items[idx]['text'],
style: TextStyle(
fontSize: 21, color: Colors.white),
),
],
),
),
),
),
],
);
}),
),
],
),
),
);
}
}
list_model.dart list_model.dart
import 'package:flutter/cupertino.dart';
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
class ListModel with ChangeNotifier {
List<Map<String, dynamic>> _items = [];
List<Map<String, dynamic>> get getItems => _items;
void addItem(Map<String, dynamic> item) {
_items.add(item);
notifyListeners();
}
void toggleValue(int idx, bool val) {
_items[idx]['value'] = val;
notifyListeners();
}
}
As mentioned in the readme files by the following link如以下链接的自述文件中所述
https://pub.dev/packages/flutter_secure_storage https://pub.dev/packages/flutter_secure_storage
The following code instantiate the storage, and the following code's must be in a async
method as this returns a future.以下代码实例化存储,并且以下代码必须在
async
方法中,因为它返回未来。
final storage = new FlutterSecureStorage();
And you can pass the _items
list as a value and you can set some key name您可以将
_items
列表作为值传递,您可以设置一些键名
await storage.write(key: key, value: _items);
And then you could get that value by using the key name (which is set while storing)然后您可以通过使用键名(在存储时设置)来获取该值
List<Map<String, dynamic>> _value = await storage.read(key: key);
And then you could map the _value
you get from storage and you can store it in _items
.然后您可以映射从存储中获得的
_value
并将其存储在_items
。 And then you could do various operations and queries inside your app now with all data you have.然后,您现在可以使用您拥有的所有数据在您的应用程序中执行各种操作和查询。
Make a note!记录下来! I haven't tried this approach in my code base.
我还没有在我的代码库中尝试过这种方法。 Just I said what I thought.
我只是说出了我的想法。 Please try this in your code and comment me please.
请在您的代码中尝试此操作并请评论我。
The following code executes correctly use this in model, for storing data:以下代码在模型中正确执行,用于存储数据:
Future<void> _storingData() async {
final storage = new FlutterSecureStorage();
for (int i = 0; i < _items.length; i++) {
await storage
.write(key: _items[i]['text'], value: "${_items[i]['value']}")
.then((value) => print("success"));
}
}
For retrieving data:用于检索数据:
Future<void> retrivingData() async {
final storage = new FlutterSecureStorage();
Map<String, String> allValues = await storage.readAll();
print(allValues);
allValues.forEach((key, value) {
bool val = bool.fromEnvironment(value, defaultValue: false);
Map<String, dynamic> item = {'value': val, 'text': key};
addItem(item);
});
}
and finally I stored all values again to a list.最后我再次将所有值存储到列表中。
You should do some changes in your code in main.dart
according to the above methods based on your usage.您应该根据您的使用情况,按照上述方法对
main.dart
中的代码进行一些更改。
You can copy paste run full code below您可以在下面复制粘贴运行完整代码
You can use class TodoItem
and save/load with JSON String您可以使用类
TodoItem
并使用 JSON 字符串保存/加载Provider
logic for secure storage is in full code, too long to describe detail安全存储的
Provider
逻辑是完整的代码,太长无法描述细节
code snippet代码片段
List<TodoItem> todoItemFromJson(String str) =>
List<TodoItem>.from(json.decode(str).map((x) => TodoItem.fromJson(x)));
String todoItemToJson(List<TodoItem> data) =>
json.encode(List<dynamic>.from(data.map((x) => x.toJson())));
class TodoItem {
TodoItem({
this.item,
this.checked,
});
String item;
bool checked;
factory TodoItem.fromJson(Map<String, dynamic> json) => TodoItem(
item: json["item"],
checked: json["checked"],
);
Map<String, dynamic> toJson() => {
"item": item,
"checked": checked,
};
}
working demo工作演示
full code完整代码
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
import 'dart:convert';
List<TodoItem> todoItemFromJson(String str) =>
List<TodoItem>.from(json.decode(str).map((x) => TodoItem.fromJson(x)));
String todoItemToJson(List<TodoItem> data) =>
json.encode(List<dynamic>.from(data.map((x) => x.toJson())));
class TodoItem {
TodoItem({
this.item,
this.checked,
});
String item;
bool checked;
factory TodoItem.fromJson(Map<String, dynamic> json) => TodoItem(
item: json["item"],
checked: json["checked"],
);
Map<String, dynamic> toJson() => {
"item": item,
"checked": checked,
};
}
class ListModel with ChangeNotifier {
FlutterSecureStorage _storage;
List<TodoItem> _items = [];
List<TodoItem> get getItems => _items;
initilaize() async {
print("initialize");
String jsonString = await _storage.read(key: "todo");
if (jsonString != null) {
_items = todoItemFromJson(jsonString);
notifyListeners();
}
}
ListModel.init(FlutterSecureStorage storage) {
print("init");
_storage = storage;
initilaize();
}
void update(FlutterSecureStorage storage) {
print("update");
_storage = storage;
}
void addItem(TodoItem item) {
_items.add(item);
notifyListeners();
}
void toggleValue(int idx, bool val) {
_items[idx].checked = val;
notifyListeners();
}
}
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
home: MultiProvider(
providers: [
Provider<FlutterSecureStorage>(create: (_) => FlutterSecureStorage()),
ChangeNotifierProxyProvider<FlutterSecureStorage, ListModel>(
create: (_) {
return ListModel.init(
Provider.of<FlutterSecureStorage>(_, listen: false));
},
update: (_, storage, listModel) => listModel..update(storage),
),
],
child: MyHomePage('Todos app example'),
),
);
}
}
class MyHomePage extends StatelessWidget {
MyHomePage(this.title);
final String title;
final TextEditingController eCtrl = TextEditingController();
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(title),
actions: <Widget>[
Consumer2<ListModel, FlutterSecureStorage>(
builder: (_, listModel, storage, __) => IconButton(
icon: Icon(Icons.save),
onPressed: () async {
await storage.write(
key: "todo", value: todoItemToJson(listModel._items));
print("save done");
},
))
],
),
body: SingleChildScrollView(
child: Column(
children: <Widget>[
Container(
padding: EdgeInsets.all(10),
child: Row(
children: <Widget>[
Expanded(
child: TextField(
decoration: InputDecoration(
border: InputBorder.none,
hintText: 'Enter your ToDo item',
),
controller: eCtrl,
),
),
Consumer<ListModel>(
builder: (_, listModel, __) => FlatButton(
child: Text('Add'),
onPressed: () {
if (eCtrl.text != '') {
Map<String, dynamic> item = {
'value': false,
'text': eCtrl.text
};
listModel.addItem(
TodoItem(item: eCtrl.text, checked: false));
eCtrl.clear();
}
},
),
),
],
),
),
Center(
child: Consumer<ListModel>(builder: (_, listModel, __) {
var items = listModel.getItems;
return Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Container(
height: 300,
child: ListView.builder(
itemCount: items.length,
itemBuilder: (BuildContext context, int idx) =>
Container(
padding: const EdgeInsets.all(5),
color: Colors.green,
child: Row(
children: <Widget>[
Checkbox(
value: items[idx].checked,
onChanged: (val) {
listModel.toggleValue(idx, val);
}),
Text(
items[idx].item,
style: TextStyle(
fontSize: 21, color: Colors.white),
),
],
),
),
),
),
],
);
}),
),
],
),
),
);
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.