简体   繁体   English

未处理的异常:FormatException:flutter(在 shared_preferences 中)的输入意外结束(在字符 1)

[英]Unhandled Exception: FormatException: Unexpected end of input (at character 1) in flutter (in shared_preferences)

I'm making a task book, on a flutter, in this project I will use a lot of packages that I have not worked with before (this is not my first question on this project).我在 flutter 上制作任务书,在这个项目中我将使用很多我以前没有使用过的包(这不是我在这个项目上的第一个问题)。 My goal is to create tasks to add to the status (finished, not finished), and save them locally on the device.我的目标是创建任务以添加到状态(已完成、未完成),并将它们保存在本地设备上。 I wrote code (with some packages to help me figure it out) that does it all.我写了代码(用一些包来帮助我弄明白)来完成这一切。 But the problem arose when downloading questions from the local repository when starting the application.但是在启动应用程序时从本地存储库下载问题时出现了问题。 I have an error not to decode the data (in the repository I save a list of our tasks and status).我有一个不解码数据的错误(在存储库中我保存了我们的任务和状态列表)。 Maybe someone faced such a problem I will be grateful for your help)也许有人遇到过这样的问题我会很感激你的帮助)

import 'dart:async';
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:testjob/jsonTodo.dart';
void main() {
  runApp(MaterialApp(
    home: App(),
  ));
}



class _strikeThrough extends StatelessWidget {
  final String todoText;
  final bool todoCheck;
  _strikeThrough(this.todoText, this.todoCheck) : super();

  Widget _widget() {
    if (todoCheck) {
      return Text(
        todoText,
        style: TextStyle(
          fontSize: 22.0,
        ),
      );
    } else {
      return Text(
        todoText,
        style: TextStyle(fontSize: 22.0),
      );
    }
  }

  @override
  Widget build(BuildContext context) {
    return _widget();
  }
}

class App extends StatefulWidget {
  @override
  AppState createState() {
    return AppState();
  }
}

final ValueNotifier<ThemeMode> _notifier = ValueNotifier(ThemeMode.light);

class AppState extends State<App> {



  bool valText = true;
  var IconsType = Icons.wb_sunny;

  late Color ColorType = Colors.black;

  var textController = TextEditingController();
  var popUpTextController = TextEditingController();

  List<TodoInfo> WidgetList = [];

  @override
  void dispose() {
    textController.dispose();
    popUpTextController.dispose();
    super.dispose();
  }

  @override
  void initState() {
    getSP();
    super.initState();
  }

  Future<void> addToSP(List<List<TodoInfo>> tList) async {
    final prefs = await SharedPreferences.getInstance();
    prefs.setString('todoLists', jsonEncode(tList));
  }

  void getSP() async {
    final prefs = await SharedPreferences.getInstance();
    final List<dynamic> jsonData =
    jsonDecode(prefs.getString('todoLists') ?? '');
    if (jsonData.isNotEmpty) {
      for (var data in jsonData) {
        final d = TodoInfo.fromJson(data);
        WidgetList.add(d);
      }
      setState(() {});
    }
  }



  @override
  Widget build(BuildContext context) {
    return ValueListenableBuilder<ThemeMode>(
        valueListenable: _notifier,
        builder: (_, mode, __) {
          return MaterialApp(
              theme: ThemeData.light(),
              darkTheme: ThemeData.dark(),
              themeMode: mode, // Decides which theme to show, light or dark.
              home: Scaffold(
                appBar: AppBar(
                  title: Text("Список задач"),
                  actions: <Widget>[
                    IconButton(
                        icon: Icon(IconsType, color: ColorType),
                        onPressed: () => {
                          if (_notifier.value == ThemeMode.light)
                            {
                              _notifier.value = ThemeMode.dark,
                              IconsType = Icons.dark_mode,
                              ColorType = Colors.white,
                            }
                          else
                            {
                              _notifier.value = ThemeMode.light,
                              IconsType = Icons.wb_sunny,
                              ColorType = Colors.black,
                            }
                        })
                  ],
//backgroundColor: Colors.orange[500],
                  iconTheme: IconThemeData(color: Colors.white),
                ),
                body: Column(
                  crossAxisAlignment: CrossAxisAlignment.center,
                  children: <Widget>[
                    Container(
                      child: Row(
                        mainAxisAlignment: MainAxisAlignment.center,
                        children: <Widget>[
                          const Text(
                            "Tasks",
                            style: TextStyle(
                              fontSize: 70.0,
                              fontWeight: FontWeight.bold,
                              color: Colors.black,
                            ),
                          ),
                          IconButton(
                            color: Colors.black,
                            iconSize: 70,
                            constraints: const BoxConstraints(),
                            padding: EdgeInsets.fromLTRB(30.0, 10.0, 30, 10.0),
                            icon: const Icon(Icons.add_outlined),
                            onPressed: () {
                              if (textController.text
                                  .replaceAll(" ", "")
                                  .isNotEmpty) {
                                WidgetList.insert(0,  TodoInfo(todoText:textController.text.replaceAll(" ", ""), todoCheck: false ));
                                addToSP;
                                setState(() {
                                  valText = true;
                                  textController.clear();
                                });
                              } else {
                                setState(() {
                                  valText = false;
                                });
                              }
                            },
                          )
                        ],
                      ),
                    ),
                    Container(
                      width: MediaQuery.of(context).size.height * 0.45,
                      child: TextField(
                        style: TextStyle(
                          fontSize: 22.0,
//color: Theme.of(context).accentColor,
                        ),
                        controller: textController,
                        cursorWidth: 5.0,
                        autocorrect: true,
                        autofocus: true,
//onSubmitted: ,
                      ),
                    ),
                    Align(
                        child: (valText == false)
                            ? Align(
                            child: Text(("Задача пустая"),
                                style: TextStyle(
                                    fontSize: 25.0, color: Colors.red)),
                            alignment: Alignment.center)
                            : Align(
                            child: Text(
                              (""),
                            ),
                            alignment: Alignment.center)),
                    Expanded(
                      child: ReorderableListView(
                        children: <Widget>[
                          for (final widget in WidgetList)
                            GestureDetector(
                              key: Key(widget.todoText),
                              child: Dismissible(
                                key: Key(widget.todoText),
                                child: CheckboxListTile(
                                  controlAffinity:
                                  ListTileControlAffinity.leading,
//key: ValueKey("Checkboxtile $widget"),
                                  value: widget.todoCheck,
                                  title: _strikeThrough(
                                      widget.todoText, widget.todoCheck),
                                  onChanged: (checkValue) {
//_strikethrough toggle
                                    setState(() {
                                      if (!checkValue!) {
                                        widget.todoCheck = false;
                                      } else {
                                        widget.todoCheck = true;
                                      }
                                    });
                                  },
                                ),
                                background: Container(
                                  child: Icon(Icons.delete),
                                  alignment: Alignment.centerRight,
                                  color: Colors.redAccent,
                                ),
                                direction: DismissDirection.endToStart,
                                movementDuration:
                                const Duration(milliseconds: 200),
                                onDismissed: (dismissDirection) {
//Delete Todo
                                  WidgetList.remove(widget);
                                },
                              ),
                            )
                        ],
                        onReorder: (oldIndex, newIndex) {
                          setState(() {
                            if (newIndex > oldIndex) {
                              newIndex -= 1;
                            }
                            var replaceWiget = WidgetList.removeAt(oldIndex);
                            WidgetList.insert(newIndex, replaceWiget);
                          });
                        },
                      ),
                    )
                  ],
                ),
              ));
        });
  }
}

class TodoInfo {
  String todoText;
  bool todoCheck;

  TodoInfo({
    required this.todoText,
    required this.todoCheck,
  });

  factory TodoInfo.fromJson(Map<String, dynamic> json) {
    return TodoInfo(todoText: json["todoText"], todoCheck: json["todoCheck"]);
  }

  factory TodoInfo.fromMap(Map<String, dynamic> map) =>
      TodoInfo(
        todoText: map["todoText"] ?? '',
        todoCheck: map["todoCheck"] ?? '',
      );

  Map<String, dynamic> toJson() {
    return {"todoText": todoText, "todoCheck": todoCheck};
  }

  @override
  String toString() => '{todoText: $todoText, todoCheck: $todoCheck}';
}

My erorr我的错误

E/flutter (30831): [ERROR:flutter/lib/ui/ui_dart_state.cc(199)] Unhandled Exception: FormatException: Unexpected end of input (at character 1)
E/flutter (30831): 
E/flutter (30831): ^
E/flutter (30831): 
E/flutter (30831): #0      _ChunkedJsonParser.fail (dart:convert-patch/convert_patch.dart:1404:5)
E/flutter (30831): #1      _ChunkedJsonParser.close (dart:convert-patch/convert_patch.dart:522:7)
E/flutter (30831): #2      _parseJson (dart:convert-patch/convert_patch.dart:41:10)
E/flutter (30831): #3      JsonDecoder.convert (dart:convert/json.dart:506:36)
E/flutter (30831): #4      JsonCodec.decode (dart:convert/json.dart:157:41)
E/flutter (30831): #5      jsonDecode (dart:convert/json.dart:96:10)
E/flutter (30831): #6      AppState.getSP (package:testjob/main.dart:85:5)
E/flutter (30831): <asynchronous suspension>
E/flutter (30831): 

Change null check value from '' to '[]' .将 null 校验值从''更改为'[]'

You set jsonData with type List .您将jsonData设置为List类型。 In case prefs.getString('todoLists') is null , jsonDecode will take '' as parameter, but '' is not a valid json and cause the FormatException .如果prefs.getString('todoLists')nulljsonDecode会将''作为参数,但''不是有效的 json并导致FormatException

// final List<dynamic> jsonData = jsonDecode(prefs.getString('todoLists') ?? '');
-> final List<dynamic> jsonData = jsonDecode(prefs.getString('todoLists') ?? '[]');

Example: decode strings.示例:解码字符串。 在此处输入图像描述

Updated: copy code in the file and paster to dartpad .更新:复制文件中的代码并粘贴到dartpad since I don't have much time, I have omitted the things that are not so important, please add it after the main thread is up and running normally to run.由于时间不多,省略了一些不太重要的东西,请等主线程正常运行后再添加。 check the dartpad console, you can see everytime you make an update to data, writeTodos was called, place your code in there (dartpad cant use sharedPref library)检查 dartpad 控制台,你可以看到每次更新数据时,writeTodos 被调用,把你的代码放在那里(dartpad 不能使用 sharedPref 库)

import 'package:flutter/material.dart';

void main() => runApp(MaterialApp(home: App()));

class App extends StatefulWidget {
  @override
  AppState createState() => AppState();
}

class AppState extends State<App> {
  final textController = TextEditingController();
  final formKey = GlobalKey<FormState>();
  List<TodoInfo> data = [];

  @override
  void initState() {
    readTodos();
    super.initState();
  }

  @override
  void dispose() {
    textController.dispose();
    super.dispose();
  }

  void submitAddTodo() {
    if (formKey.currentState?.validate() ?? false) {
      final todoString = textController.text;
      if (todoString.isNotEmpty) {
        var todo = TodoInfo(todoText: todoString.trim(), todoCheck: false);
        addTodo(todo);
        textController.clear();
      }
    }
  }

  void removeTodoAt(int index) {
    setState(() {
      data = [...data]..removeAt(index);
      writeTodos();
    });
  }

  void updateTodoAt(int index, TodoInfo todo) {
    setState(() {
      data[index] = todo;
      writeTodos();
    });
  }

  void addTodo(TodoInfo todo) {
    setState(() {
      data = [todo, ...data];
      writeTodos();
    });
  }

  Future<void> writeTodos() async {
    // write data to shared
    print('writeTodos');
  }

  void readTodos() async {
    print('readTodos');
    // read data from your shared insteads hard code `prefsData`
    final prefsData = [
      TodoInfo(todoText: 'todo 1', todoCheck: false),
      TodoInfo(todoText: 'todo 2', todoCheck: false),
    ];
    setState(() => data = prefsData);
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      //...
      body: Form(
        key: formKey,
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.center,
          children: <Widget>[
            Container(
              child: Row(
                mainAxisAlignment: MainAxisAlignment.center,
                children: <Widget>[
                  const Text(
                    "Tasks",
                    style: TextStyle(
                      fontSize: 70.0,
                      fontWeight: FontWeight.bold,
                      color: Colors.black,
                    ),
                  ),
                  IconButton(
                    color: Colors.black,
                    iconSize: 70,
                    constraints: const BoxConstraints(),
                    padding: EdgeInsets.fromLTRB(30.0, 10.0, 30, 10.0),
                    icon: const Icon(Icons.add_outlined),
                    onPressed: submitAddTodo,
                  )
                ],
              ),
            ),
            Container(
              width: MediaQuery.of(context).size.height * 0.45,
              child: TextFormField(
                style: TextStyle(fontSize: 22.0),
                controller: textController,
                autofocus: true,
                validator: (value) {
                  if (value == null || value.isEmpty) return 'Список задач';
                },
              ),
            ),
            Expanded(child: _rTodos())
          ],
        ),
      ),
    );
  }

  Widget _rTodos() {
    var wgs = <Widget>[];
    for (int i = 0; i < data.length; i++) {
      var todo = data[i];
      wgs.add(GestureDetector(
        child: CheckboxListTile(
          controlAffinity: ListTileControlAffinity.leading,
          value: todo.todoCheck,
          title: Text(todo.todoText, style: TextStyle(fontSize: 22.0)),
          onChanged: (checkValue) =>
              updateTodoAt(i, todo..todoCheck = checkValue ?? false),
        ),
      ));
    }
    return ListView(
      children: wgs
    );
  }
}

class TodoInfo {
  String todoText;
  bool todoCheck;

  TodoInfo({required this.todoText, required this.todoCheck});
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 未处理的异常:FormatException:意外的输入结束(在字符 1) - Unhandled Exception: FormatException: Unexpected end of input (at character 1) 未处理的异常:FormatException:输入意外结束(在字符 2 处) - Unhandled Exception: FormatException: Unexpected end of input (at character 2) Flutter 未处理异常:FormatException:意外字符(在字符 4) - Flutter Unhandled Exception: FormatException: Unexpected character (at character 4) Flutter:未处理的异常:FormatException:意外字符(在字符 1) - Flutter: Unhandled Exception: FormatException: Unexpected character (at character 1) 未处理的异常:FormatException:意外字符(在字符 1 处)Flutter - Unhandled Exception: FormatException: Unexpected character (at character 1) Flutter I/flutter:FormatException:输入意外结束(在字符 1 处) - I/flutter : FormatException: Unexpected end of input (at character 1) FormatException:输入意外结束(在字符 2 处)^ 在 flutter - FormatException: Unexpected end of input (at character 2) ^ in flutter 错误 Flutter (186)] 未处理异常:FormatException:意外字符(在字符 1) - Error Flutter (186)] Unhandled Exception: FormatException: Unexpected character (at character 1) Flutter:http.get() 未处理异常:FormatException:意外字符(在字符 1) - Flutter: http.get() Unhandled Exception: FormatException: Unexpected character (at character 1) Flutter - 未处理的异常:FormatException:意外字符(字符 1)| 响应实例 - Flutter - Unhandled Exception: FormatException: Unexpected character (at character 1) | Instance of Response
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM