首页 > 解决方案 > 数据持久化 - 如何持久化数据列表

问题描述

我有一个需要保留的数据列表,但我不知道从哪里开始,我正在制作的一些背景知识。一个通过 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,
                                        ),
                                      ),
                                    )
                                  ],
                                )
                              ],
                            ),
                          ]),
                    ),
                  ),
                );
              }
          ),
        ),
      ),
    );
  }



}

如果您需要更多上下文,请完全免费让我知道。

标签: flutter

解决方案


如果您不打算拥有成百上千个控制器,我建议使用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 服务器获取数据。


推荐阅读