使用 sharedPrefrences 或 JSON 保存用户数据(采用我的 class 格式)

Saving user data(which is in my class format) with sharedPrefrences or JSON

刚学完Flutter的课程,上一个项目是一个简单的Todo-List,关掉app后没有任务,真是苦恼。 课程的完整代码是 here

我的代码完全没有区别:

我非常喜欢提供程序和任务 class 的工作方式,所以我不想更改它,所以我尝试按原样保存数据,方法是制作两个列表,一个用于字符串,另一个用于布尔值取出来保存(写入),然后读取并放回原处(读取)
理论上像这样——循环内的 Task(StringList[index],boolList[index])——作为 Task class; 的方面当我尝试使用 SharedPreferences 保存时,我制作了一个虚拟代码,使添加任务不起作用

任何节省方式都会有所帮助,我的虚拟想法或任何东西。

'data' class 其中 sharedPreferences 尝试:

import 'dart:collection';

import 'package:flutter/foundation.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'tasks.dart';
class TaskData extends ChangeNotifier{


 List<Task> _tasks = [];

  UnmodifiableListView<Task> get tasks => UnmodifiableListView(_tasks);

  int get taskCount => _tasks.length;

  String _string;
  String _bool;

  void addTask(String newTaskName) async{
    final task = Task(name: newTaskName);
    _tasks.add(task);

// here is the code

    SharedPreferences sPref = await SharedPreferences.getInstance();
    List<SharedPreferences> sPrefs =[];
    SharedPreferences bPref = await SharedPreferences.getInstance();
    List<SharedPreferences> bPrefs =[];

    for(var item = 0; item <= taskCount; item++){
      //String Preferences
      sPref.setString(_string, tasks[item].name);
      sPrefs.add(sPref);

      //boolean Preferences
      bPref.setBool(_bool,tasks[item].isDone);
      bPrefs.add(bPref);
    }

// code is finished

    notifyListeners();
  }
  void updateTask(Task task){
    task.toggleIsDone();
    notifyListeners();
  }
  void removeTask(Task task){
    _tasks.remove(task);
    notifyListeners();
  }


}

tasks class(数据保存在tasks数组中的方式)

class Task {
  final String name;
  bool isDone;

  Task({this.name, this.isDone = false});

  void toggleIsDone() {
    isDone = !isDone;
  }
}

现在有其他 class 涉及但与 github 代码

没有区别

添加任务:

import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
import 'package:provider/provider.dart';
import 'package:todoey_flutter/components/constants.dart';
import 'package:todoey_flutter/modules/task_data.dart';


class AddTaskScreen extends StatelessWidget {
  final controller = TextEditingController();
  @override
  Widget build(BuildContext context) {
    String userTask;
    return Container(
      color: Color(0xFF737373),
      height: 600,
      child: Container(
        padding: EdgeInsets.all(36.0),
        decoration: kContainerBoxRadius,
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.stretch,
          children: <Widget>[
            Text(
              'Add a Task',
              style: TextStyle(
                  color: Colors.lightBlueAccent,
                  fontSize: 36,
                  fontWeight: FontWeight.w300),
              textAlign: TextAlign.center,
            ),
            Padding(
              padding: EdgeInsets.symmetric(horizontal: 12.0),
              child: TextField(
                style: TextStyle(
                    fontSize: 24.0,
                    fontWeight: FontWeight.w400,
                    color: Colors.lightBlueAccent.shade700),
                onChanged: (inputTask) {
                  userTask = inputTask;
                },
                autofocus: true,
                cursorRadius: Radius.circular(32.0),
                enableSuggestions: true,
                enabled: true,
                expands: false,
                controller: controller,
                textAlign: TextAlign.center,
              ),
            ),
            SizedBox(
              height: 12.0,
            ),
            MaterialButton(
              onPressed: () {
                if (userTask == null) {}
                else {
                  controller.clear();
                  Provider.of<TaskData>(context).addTask(userTask);
                  print(TaskData().taskCount);
                  Navigator.pop(context);
                }
              },
              child: Padding(
                padding: const EdgeInsets.all(12.0),
                child: Text(
                  'ADD',
                  style: TextStyle(
                      fontSize: 22.0,
                      fontWeight: FontWeight.bold,
                      color: Colors.white),
                ),
              ),
              color: Colors.lightBlueAccent,
            ),
          ],
        ),
      ),
    );
  }
}

任务列表:

import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
import 'package:provider/provider.dart';
import 'package:todoey_flutter/modules/task_data.dart';
import 'task_tile.dart';

class TaskList extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Consumer<TaskData>(
      builder: (context, taskData, child) {
        return ListView.builder(
          itemBuilder: (context, index) {
            final task = taskData.tasks[index];
            return TaskTile(
                text: task.name,
                isChecked: task.isDone,
                toggleCheckBoxState: (bool newValue) =>
                    taskData.updateTask(task),
                longPressIdentify: () => taskData.removeTask(task),
            );
          },
          itemCount: taskData.taskCount,
        );
      },
    );
  }
}

TaskTile class 带有一些构造函数,Task class 或其中的数据没有用处

最后从main.dart>>(供应商所在的地方)任务屏幕class:

//a lot of imports mainly task_data and task list and provider and adding tasks class

class TaskScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: Colors.lightBlueAccent,
      floatingActionButton: Padding(
        padding: const EdgeInsets.only(bottom: 42.0, right: 36.0),
        child: FloatingActionButton(
            child: Icon(
              Icons.add,
              size: 48.0,
              color: Colors.white,
            ),
            backgroundColor: Colors.lightBlueAccent,
            onPressed: () {
              showModalBottomSheet(
                context: context,
                builder: (context) => AddTaskScreen(),
              );
            }),
      ),
      body: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: <Widget>[
            Container(
              padding: EdgeInsets.only(
                  left: 50.0, top: 120.0, right: 30.0, bottom: 50.0),
              child: Column(
                crossAxisAlignment: CrossAxisAlignment.start,
                children: <Widget>[
                  CircleAvatar(
                    child: Icon(
                      Icons.list,
                      color: Colors.lightBlueAccent,
                      size: 60.0,
                    ),
                    backgroundColor: Colors.white,
                    radius: 40.0,
                  ),
                  SizedBox(
                    height: 36.0,
                  ),
                  Text(
                    'Todoey',
                    style: TextStyle(
                      color: Colors.white,
                      fontWeight: FontWeight.w800,
                      fontSize: 55.0,
                    ),
                  ),
                  SizedBox(
                    height: 4.0,
                  ),
                  Padding(
                    padding: const EdgeInsets.only(left: 8.0),
                    child: Text(
                      '${Provider.of<TaskData>(context).taskCount} Tasks',
                      style: TextStyle(
                        color: Colors.white,
                        fontSize: 18.0,
                      ),
                    ),
                  ),
                ],
              ),
            ),
            Expanded(
              child: Container(
                decoration: kContainerBoxRadius,
                child: TaskList(),
              ),
            ),
          ]),
    );
  }
}

抱歉,我没有删除布局代码,所以代码块变大了 提前致谢。

您可以复制粘贴 运行 下面的完整代码
可以将List<Task>转成JSON字符串,直接保存这个JSON字符串
当您的 APP init() 时,您可以读取此 JSON 字符串并转换回 List<Task>
代码片段

 void main() {
  runApp(MultiProvider(
    providers: [
      ChangeNotifierProvider(
        create: (context) => TaskData()..init(),
      ),
    ],
    child: MyApp(),
  ));
}

 List<Task> taskFromJson(String str) =>
    List<Task>.from(json.decode(str).map((x) => Task.fromJson(x)));

 String taskToJson(List<Task> data) =>
    json.encode(List<dynamic>.from(data.map((x) => x.toJson())));
    
 void init() async {
    SharedPreferences sPref = await SharedPreferences.getInstance();
    String jsonTask = sPref.getString("task");
    print(jsonTask);
    if (jsonTask != null) {
      _tasks = taskFromJson(jsonTask);
      notifyListeners();
    }
  }

  void saveToPreference() async {
    SharedPreferences sPref = await SharedPreferences.getInstance();
    sPref.setString("task", taskToJson(_tasks));
  }

  void addTask(String newTaskName) async {
    final task = Task(name: newTaskName);
    _tasks.add(task);
    await saveToPreference();
    notifyListeners();
  }

工作演示

完整代码

import 'dart:collection';
import 'dart:convert';

import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:shared_preferences/shared_preferences.dart';

class TaskTile extends StatelessWidget {
  final bool isChecked;
  final String text;
  final Function toggleCheckBoxState;
  final Function longPressIdentify;

  TaskTile(
      {this.isChecked,
      this.text,
      this.toggleCheckBoxState,
      this.longPressIdentify});

  @override
  Widget build(BuildContext context) {
    return ListTile(
      onLongPress: longPressIdentify,
      title: Text(
        text,
        style: TextStyle(
            decoration: isChecked ? TextDecoration.lineThrough : null),
      ),
      trailing: Checkbox(
        activeColor: Colors.lightBlueAccent,
        value: isChecked,
        onChanged: toggleCheckBoxState,
      ),
    );
  }
}

class TaskList extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Consumer<TaskData>(
      builder: (context, taskData, child) {
        return ListView.builder(
          itemBuilder: (context, index) {
            final task = taskData.tasks[index];
            return TaskTile(
              text: task.name,
              isChecked: task.isDone,
              toggleCheckBoxState: (bool newValue) => taskData.updateTask(task),
              longPressIdentify: () => taskData.removeTask(task),
            );
          },
          itemCount: taskData.taskCount,
        );
      },
    );
  }
}

class AddTaskScreen extends StatefulWidget {
  @override
  _AddTaskScreenState createState() => _AddTaskScreenState();
}

class _AddTaskScreenState extends State<AddTaskScreen> {
  final controller = TextEditingController();

  String userTask;

  @override
  Widget build(BuildContext context) {
    return Container(
      color: Color(0xFF737373),
      height: 600,
      child: Container(
        padding: EdgeInsets.all(36.0),
        //decoration: kContainerBoxRadius,
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.stretch,
          children: <Widget>[
            Text(
              'Add a Task',
              style: TextStyle(
                  color: Colors.lightBlueAccent,
                  fontSize: 36,
                  fontWeight: FontWeight.w300),
              textAlign: TextAlign.center,
            ),
            Padding(
              padding: EdgeInsets.symmetric(horizontal: 12.0),
              child: TextField(
                style: TextStyle(
                    fontSize: 24.0,
                    fontWeight: FontWeight.w400,
                    color: Colors.lightBlueAccent.shade700),
                onChanged: (inputTask) {
                  userTask = inputTask;
                },
                //autofocus: true,
                cursorRadius: Radius.circular(32.0),
                enableSuggestions: true,
                enabled: true,
                expands: false,
                controller: controller,
                textAlign: TextAlign.center,
              ),
            ),
            SizedBox(
              height: 12.0,
            ),
            MaterialButton(
              onPressed: () {
                print(controller.text);
                print("onpressed $userTask");
                if (userTask == null) {
                } else {
                  controller.clear();
                  Provider.of<TaskData>(context, listen: false)
                      .addTask(userTask);
                  print(TaskData().taskCount);
                  Navigator.pop(context);
                }
              },
              child: Padding(
                padding: const EdgeInsets.all(12.0),
                child: Text(
                  'ADD',
                  style: TextStyle(
                      fontSize: 22.0,
                      fontWeight: FontWeight.bold,
                      color: Colors.white),
                ),
              ),
              color: Colors.lightBlueAccent,
            ),
          ],
        ),
      ),
    );
  }
}

List<Task> taskFromJson(String str) =>
    List<Task>.from(json.decode(str).map((x) => Task.fromJson(x)));

String taskToJson(List<Task> data) =>
    json.encode(List<dynamic>.from(data.map((x) => x.toJson())));

class Task {
  final String name;
  bool isDone;

  Task({this.name, this.isDone = false});

  void toggleIsDone() {
    isDone = !isDone;
  }

  factory Task.fromJson(Map<String, dynamic> json) => Task(
        name: json["name"],
        isDone: json["isDone"],
      );

  Map<String, dynamic> toJson() => {
        "name": name,
        "isDone": isDone,
      };
}

class TaskData extends ChangeNotifier {
  List<Task> _tasks = [];

  UnmodifiableListView<Task> get tasks => UnmodifiableListView(_tasks);

  int get taskCount => _tasks.length;

  String _string;
  String _bool;

  void init() async {
    SharedPreferences sPref = await SharedPreferences.getInstance();
    String jsonTask = sPref.getString("task");
    print(jsonTask);
    if (jsonTask != null) {
      _tasks = taskFromJson(jsonTask);
      notifyListeners();
    }
  }

  void saveToPreference() async {
    SharedPreferences sPref = await SharedPreferences.getInstance();
    sPref.setString("task", taskToJson(_tasks));
  }

  void addTask(String newTaskName) async {
    final task = Task(name: newTaskName);
    _tasks.add(task);
    await saveToPreference();
    notifyListeners();
  }

  void updateTask(Task task) async {
    task.toggleIsDone();
    await saveToPreference();
    notifyListeners();
  }

  void removeTask(Task task) async {
    _tasks.remove(task);
    await saveToPreference();
    notifyListeners();
  }
}

class TaskScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: Colors.lightBlueAccent,
      floatingActionButton: Padding(
        padding: const EdgeInsets.only(bottom: 42.0, right: 36.0),
        child: FloatingActionButton(
            child: Icon(
              Icons.add,
              size: 48.0,
              color: Colors.white,
            ),
            backgroundColor: Colors.lightBlueAccent,
            onPressed: () {
              showModalBottomSheet(
                context: context,
                builder: (context) => AddTaskScreen(),
              );
            }),
      ),
      body: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: <Widget>[
            Container(
              padding: EdgeInsets.only(
                  left: 50.0, top: 120.0, right: 30.0, bottom: 50.0),
              child: Column(
                crossAxisAlignment: CrossAxisAlignment.start,
                children: <Widget>[
                  CircleAvatar(
                    child: Icon(
                      Icons.list,
                      color: Colors.lightBlueAccent,
                      size: 60.0,
                    ),
                    backgroundColor: Colors.white,
                    radius: 40.0,
                  ),
                  SizedBox(
                    height: 36.0,
                  ),
                  Text(
                    'Todoey',
                    style: TextStyle(
                      color: Colors.white,
                      fontWeight: FontWeight.w800,
                      fontSize: 55.0,
                    ),
                  ),
                  SizedBox(
                    height: 4.0,
                  ),
                  Padding(
                    padding: const EdgeInsets.only(left: 8.0),
                    child: Text(
                      '${Provider.of<TaskData>(context).taskCount} Tasks',
                      style: TextStyle(
                        color: Colors.white,
                        fontSize: 18.0,
                      ),
                    ),
                  ),
                ],
              ),
            ),
            Expanded(
              child: Container(
                //decoration: kContainerBoxRadius,
                child: TaskList(),
              ),
            ),
          ]),
    );
  }
}

void main() {
  runApp(MultiProvider(
    providers: [
      ChangeNotifierProvider(
        create: (context) => TaskData()..init(),
      ),
    ],
    child: MyApp(),
  ));
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      home: TaskScreen(),
    );
  }
}