我是Flutter和Dart的新手。我用提供程序包和Consumer制作了一个简单的Todos应用程序。我正在尝试实现一个使用flutter_secure_storage包读取和写入设备上的列表数据的过程。 但是我不知道如何实现。
复选框小部件需要布尔值,而secure_storage则需要字符串类型。因此,有必要转换两种类型。这也让我有些困惑。
代码在下面。 如果您能给我一些建议,我会很高兴。
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
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();
}
}
答案 0 :(得分:0)
如自述文件中通过以下链接所述
https://pub.dev/packages/flutter_secure_storage
以下代码实例化存储,并且以下代码必须位于async
方法中,因为这将返回将来。
final storage = new FlutterSecureStorage();
您可以将_items
列表作为值传递,并且可以设置一些键名
await storage.write(key: key, value: _items);
然后您可以使用密钥名称(在存储时设置)获取该值
List<Map<String, dynamic>> _value = await storage.read(key: key);
然后您可以映射从存储中获取的_value
并将其存储在_items
中。然后,您现在就可以对应用中的所有数据进行各种操作和查询。
记笔记!我没有在代码库中尝试过这种方法。我只是说了我的想法。请在您的代码中尝试使用此代码,然后对我发表评论。
以下代码在模型中使用此代码正确执行,用于存储数据:
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"));
}
}
用于检索数据:
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);
});
}
最后,我再次将所有值存储到列表中。
您应根据使用情况,根据上述方法对main.dart
中的代码进行一些更改。
答案 1 :(得分:0)
您可以在下面复制粘贴运行完整代码
您可以使用类TodoItem
并使用JSON字符串保存/加载
Provider
用于安全存储的逻辑是完整代码,太长,无法描述细节
代码段
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,
};
}
工作演示
完整代码
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),
),
],
),
),
),
),
],
);
}),
),
],
),
),
);
}
}