【问题标题】:Saving user data(which is in my class format) with sharedPrefrences or JSON使用 sharedPrefrences 或 JSON 保存用户数据(我的类格式)
【发布时间】:2020-12-31 18:50:17
【问题描述】:

我刚刚完成了一个学习 Flutter 的课程,上一个项目是一个简单的 Todo-List,关闭应用后任务不能在那里真的很烦人。 课程的完整代码是here

我的代码完全没有区别:

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

任何保存方法都会有所帮助,我的愚蠢想法或任何东西。

sharedPreferences 尝试的'data'类:

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 类(数据保存在tasks数组中的方式)

class Task {
  final String name;
  bool isDone;

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

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

现在涉及到的其他类,但与 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 是具有一些构造函数的类,其中的 Task 类或数据没有用处

最后是 main.dart 中的主要子类>>(提供者所在的位置)任务屏幕:

//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(),
              ),
            ),
          ]),
    );
  }
}

对不起,我没有删除布局代码,所以它会使代码块变大 提前致谢。

【问题讨论】:

    标签: flutter dart sharedpreferences


    【解决方案1】:

    您可以在下面复制粘贴运行完整代码
    您可以将List&lt;Task&gt; 转换为JSON 字符串并直接保存这个JSON 字符串
    当您的APP init() 时,您可以读取此JSON 字符串并转换回List&lt;Task&gt;
    代码sn-p

     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(),
        );
      }
    }
    

    【讨论】:

      猜你喜欢
      • 2016-10-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-01-24
      • 2023-03-29
      • 1970-01-01
      • 2019-04-11
      • 1970-01-01
      相关资源
      最近更新 更多