flutter - 数据持久化 - 如何持久化数据列表
问题描述
我有一个需要保留的数据列表,但我不知道从哪里开始,我正在制作的一些背景知识。一个通过 http 请求控制 raspberry pi 的 gpio 引脚的应用程序,尽管目前我只是在 ui 上工作并且还没有真正开始让 web 服务器来处理 http 请求。
以下是我用于开发的模型以及我要保存的模型。
class Pin {
int index;
int pinNum;
String name;
bool isOn;
Pin (int pinNum, String name, bool isOn, int index) {
this.pinNum = pinNum;
this.name = name;
this.isOn = isOn;
this.index = index;
}
}
Pin controller1 = Pin(18, "light", true, 0);
Pin controller2 = Pin(20, "tv", false, 1);
Pin controller3 = Pin(24, "blender", true, 2);
Pin controller4 = Pin(34, "television", false, 3);
List <Pin>controllers = [
controller1,
controller2,
controller3,
controller4,
];
这是我的列表视图构建器所在的代码(抱歉,我仍在学习糟糕的格式)
import 'package:flutter/material.dart';
import "package:gpio_control/models/pin.dart";
import 'package:slide_popup_dialog/slide_popup_dialog.dart' as slideDialog;
class GpioScreen extends StatefulWidget {
@override
_GpioScreenState createState() => _GpioScreenState();
}
class _GpioScreenState extends State<GpioScreen> {
@override
Widget build(BuildContext context) {
int selectedIndex = 0;
return Scaffold(
backgroundColor: Colors.grey[850],
floatingActionButtonLocation: FloatingActionButtonLocation.centerFloat,
appBar: AppBar(
title: Text(
"Gpio Control",
style: TextStyle(
color: Colors.yellow[200]
),
),
backgroundColor: Colors.black26,
centerTitle: true,
elevation: 1,
actions: <Widget>[
IconButton(
icon: Icon(
Icons.settings,
color: Colors.yellow[200],
),
iconSize: 40,
onPressed: () {
Navigator.pushNamed(context, '/settings');
}, //settings
)
],
),
floatingActionButton: SizedBox(
width: 200,
height: 40,
child: FloatingActionButton(
elevation: 2,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(45)
),
backgroundColor: Colors.yellow[200],
onPressed: () {
Navigator.pushNamed(context, '/addPin');
},
child: Icon(
Icons.add,
color: Colors.black54,
size: 30,
),
),
),
body: Container(
child: Padding(
padding: const EdgeInsets.only(bottom: 80),
child: ListView.builder(
itemCount: controllers.length,
itemBuilder: (context, i) {
void _showDialog() {
slideDialog.showSlideDialog(
context: context,
child: Column(
children: <Widget>[
Padding(
padding: const EdgeInsets.fromLTRB(20,80,5,10),
child: Text(
"Are you sure you want to delete this configuration?",
style: TextStyle(
color: Colors.yellow[200],
fontSize: 20,
fontWeight: FontWeight.bold
),
),
),
Text(
"(Any deleted configurations can not be recoved)",
style: TextStyle(
color: Colors.yellow[200],
fontSize: 10,
fontWeight: FontWeight.bold
),
),
Padding(
padding: const EdgeInsets.only(top: 0),
child: ButtonTheme(
minWidth: 300,
child: FlatButton(
onPressed: () {
setState(() {
selectedIndex = i;
controllers.remove(controllers.removeAt(selectedIndex));
Navigator.of(context).pop();
});
},
color: Colors.yellow[200],
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(30.0),
side: BorderSide(color: Colors.yellow[200])
),
child: Text(
"Delete"
),
),
),
),
],
),
barrierColor: Colors.yellow[100].withOpacity(0.7),
pillColor: Colors.yellow[200],
backgroundColor: Colors.black54,
);
}
return Padding(
padding: const EdgeInsets.all(8.0),
child: Card(
color: Colors.yellow[200],
child: Padding(
padding: const EdgeInsets.fromLTRB(25, 0, 0, 0),
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
Row(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
Padding(
padding: const EdgeInsets.fromLTRB(6, 6, 0, 0),
child: Text("pin"),
),
],
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Padding(
padding: const EdgeInsets.only(bottom: 15),
child: Text(
controllers[i].pinNum.toString(),
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 25
),
),
),
Row(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment
.spaceEvenly,
children: <Widget>[
Center(
child: Padding(
padding: const EdgeInsets.fromLTRB(
25, 0, 0, 25),
child: Text(
controllers[i].name,
style: TextStyle(
fontSize: 20,
fontWeight: FontWeight.w400
),
),
),
),
],
),
Row(
mainAxisAlignment: MainAxisAlignment
.spaceEvenly,
children: <Widget>[
Padding(
padding: const EdgeInsets.fromLTRB(
0, 0, 10, 20),
child: IconButton(
onPressed: () {
setState(() {
if (controllers[i].isOn) {
controllers[i].isOn = false;
print(controllers[i].isOn);
}
else {
controllers[i].isOn = true;
}
});
},
icon: Icon(
Icons.power_settings_new,
color: controllers[i].isOn == true
? Colors.green[600]
: Colors.red[600]
),
color: Colors.yellow[150],
),
),
Padding(
padding: const EdgeInsets.fromLTRB(
0, 0, 0, 20),
child: GestureDetector(
onTap: () {
setState(() {
selectedIndex = i;
print("new index");
});
},
child: IconButton(
onPressed: () {
_showDialog();
},
icon: Icon(Icons.delete),
iconSize: 30,
),
),
)
],
)
],
),
]),
),
),
);
}
),
),
),
);
}
}
如果您需要更多上下文,请完全免费让我知道。
解决方案
如果您不打算拥有成百上千个控制器,我建议使用Shared Preferences而不是使用 SQLite,它更容易并且几乎不存在性能损失。
您可以为每个控制器手动声明每个键:值对,但这不是一个好的解决方案,特别是如果您将来最终需要更多控制器。相反,我建议修改您的 Pin 类以包含 json 到/从映射,以及另外一个类来存储所有引脚,如下所示:
class AllPins {
List<Pin> allPins;
AllPins(this.allPins);
AllPins.fromJson(Map<String, dynamic> json) {
if (json['AllPins'] != null) {
allPins = new List<Pin>();
json['AllPins'].forEach((v) {
allPins.add(new Pin.fromJson(v));
});
}
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
if (this.allPins != null) {
data['AllPins'] = this.allPins.map((v) => v.toJson()).toList();
}
return data;
}
}
class Pin {
int index;
int pinNum;
String name;
bool isOn;
Pin (int index, int pinNum, String name, bool isOn) {
this.pinNum = pinNum;
this.name = name;
this.isOn = isOn;
this.index = index;
}
Pin.fromJson(Map<String, dynamic> json) {
index = json['index'];
pinNum = json['pinNum'];
name = json['name'];
isOn = json['isOn'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['index'] = this.index;
data['pinNum'] = this.pinNum;
data['name'] = this.name;
data['isOn'] = this.isOn;
return data;
}
}
然后创建用于从共享首选项中加载/保存/删除 AllPins 的方法,如下所示:
import 'dart:convert';
// load
Future<AllPins> loadAllPins() async {
SharedPreferences prefs = await SharedPreferences.getInstance();
var allPinsTemp = prefs.getString('AllPins');
if(allPinsTemp!=null){
return(AllPins.fromJson(json.decode(allPinsTemp)));
}else{
return null;
}
}
// save
saveAllPins(AllPins allPins) async {
SharedPreferences prefs = await SharedPreferences.getInstance();
await prefs.setString("AllPins",json.encode(allPins.toJson()));
}
// delete
deleteAllPins() async {
SharedPreferences prefs = await SharedPreferences.getInstance();
await prefs.remove("AllPins");
}
最后是如何在应用程序的某处使用上面的代码:
await deleteAllPins();
List<Pin> pinList = new List<Pin>();
pinList.add(new Pin(1,4,"test1",true));
pinList.add(new Pin(2,7,"test2",false));
AllPins allPins = new AllPins(pinList);
await saveAllPins(allPins);
AllPins allPinsReadFromSP = await loadAllPins();
if(allPinsReadFromSP != null){
print("Total pins loaded: " + allPinsReadFromSP.allPins.length.toString());
for(int i=0; i<allPinsReadFromSP.allPins.length; i++){
print("i:"+i.toString());
print("index: " + allPinsReadFromSP.allPins[i].index.toString());
print("pinNum: " + allPinsReadFromSP.allPins[i].pinNum.toString());
print("name: " + allPinsReadFromSP.allPins[i].name);
print("isOn: " + allPinsReadFromSP.allPins[i].isOn.toString());
}
}else{
print("Null was returned for AllPins.");
}
作为额外的奖励,您可以稍后使用已经制作的 json 映射来发布/从您的 Web 服务器获取数据。
推荐阅读
- android - 我的 gridView 没有显示在 mainactivity
- javascript - 带有三元组的 Javascript 函数语法 =>
- angular-cli - 使用 @angular-builders/custom-webpack 使用 --watch 在 Angular 构建后添加任务
- ms-access - MS-Access Pro Plus 2016“无法使用”
'; 文件已在使用”Win 10 Pro 64 位 v1909 - javascript - 无法正确使用语义标签
- c# - Visual Studio 解决方案中嵌入式数据库的 SQL 连接字符串
- javascript - 模拟 javascript ES6 构造函数的可接受方式?
- google-play-console - 错误状态:在 Google Play 控制台中创建订阅时出现无人认领的错误
- c# - 将 HTTP 流量从一台 PC 重定向到另一台 PC 的任何方式
- database - Docker 容器上的 Oracle 12c 数据库,状态:不健康