Я пытаюсь использовать значения, сохраненные в SharedPreferences, для инициализации нескольких переменных в моем приложении.Во Flutter SharedPreferences являются асинхронными, поэтому в результате код, инициализируемый позже в коде, создает проблемы с моим приложением, поскольку некоторые переменные равны нулю при вызове метода сборки.
Вот небольшойтестовое приложение Flutter, которое я написал, чтобы продемонстрировать эту проблему:
import 'package:flutter/material.dart';
import 'package:flutter/cupertino.dart';
import 'package:path_provider/path_provider.dart';
import 'dart:io';
import 'dart:convert';
import 'package:shared_preferences/shared_preferences.dart';
class TestingApp extends StatefulWidget {
TestingApp() {}
@override
State<StatefulWidget> createState() {
// TODO: implement createState
return new _CupertinoNavigationState();
}
}
class _CupertinoNavigationState extends State<TestingApp> {
int itemNo;
@override
void initState() {
super.initState();
// SharedPreferences.getInstance().then((sp) {
// sp.setInt("itemNo", 3);
// });
SharedPreferences.getInstance().then((sp) {
print("sp " + sp.getInt("itemNo").toString());
setState(() {
itemNo = sp.getInt("itemNo");
});
});
print("This is the item number " + itemNo.toString());
}
@override
Widget build(BuildContext context) {
// TODO: implement build
print("item number on build " + itemNo.toString());
return new Text("Hello");
}
}
Это результат в консоли:
Performing full restart...
flutter: This is the item number null
flutter: item number on build null // build method being called and variable is null
Restarted app in 1 993ms.
flutter: sp 3
flutter: item number on build 3
Вы можете видеть это, когда я пытался получить переменную из SharedPreferences назапуска, поскольку SharedPreference является асинхронным, itemNo имеет значение null.Затем приложение запускает метод сборки и запускает метод сборки для itemNo = null, что приводит к сбоям в приложении.
Как только оно получает значение из SharedPreferences, я вызываю setState, который затем вызывает метод сборки сновас правильным значением.Однако первоначальный вызов для сборки с itemNo = null не должен был произойти.
Я хотел бы, чтобы был метод синхронизации для SharedPreferences, но он, кажется, не существует.Как запустить приложение, чтобы переменные правильно инициализировались во Flutter при запуске?
Я попытался решить эту проблему, используя синхронный метод для инициализации моих переменных, записав в файл json и затем прочитав его, используяследующее короткое тестовое приложение Flutter - мне кажется, это излишне для сохранения переменной для инициализации, но я все же попробовал:
import 'package:flutter/material.dart';
import 'package:flutter/cupertino.dart';
import 'package:path_provider/path_provider.dart';
import 'dart:io';
import 'dart:convert';
import 'package:shared_preferences/shared_preferences.dart';
class TestingApp extends StatefulWidget {
TestingApp() {}
@override
State<StatefulWidget> createState() {
// TODO: implement createState
return new _CupertinoNavigationState();
}
}
class _CupertinoNavigationState extends State<TestingApp> {
int itemNo;
File jsonFile;
String fileName = "items.json";
Directory dir;
bool fileExists = false;
void createFile(Map content, Directory dir, String fileName) {
// print("Creating file for category " + dir.path);
File file = new File(dir.path + "/" + fileName);
file.createSync();
fileExists = true;
file.writeAsStringSync(json.encode(content));
}
void writeToFile(int itemNo) {
// print("Writing to category file");
Map itemMap = new Map();
itemMap['item'] = itemNo;
if (fileExists) {
print("category file exists");
Map jsonFileContent = json.decode(jsonFile.readAsStringSync());
jsonFileContent.addAll(itemMap);
jsonFile.writeAsStringSync(json.encode(itemMap));
} else {
print("category File does not exists");
getApplicationDocumentsDirectory().then((Directory directory) {
dir = directory;
createFile(itemMap, dir, fileName);
});
}
}
fetchSavedItemNo() {
//load the currency from the saved json file.
getApplicationDocumentsDirectory().then((Directory directory) {
dir = directory;
jsonFile = new File(dir.path+ "/" + fileName);
fileExists = jsonFile.existsSync();
setState(() {
if (fileExists)
itemNo = json.decode(jsonFile.readAsStringSync())['item'];
print("fetching saved itemNo " +itemNo.toString());
if (itemNo == null) {
itemNo = 0;
}
});
return itemNo;
//else the itemNo will just be 0
});
}
@override
void initState() {
super.initState();
writeToFile(3);
setState(() {
itemNo = fetchSavedItemNo();
});
}
@override
Widget build(BuildContext context) {
// TODO: implement build
print("item number on build " + itemNo.toString());
return new Text("Hello");
}
}
У меня все еще есть результаты, когда вызывается метод сборкидо полной инициализации переменных, что вызывает сбои приложения.
Performing full restart...
flutter: category File does not exists
flutter: item number on build null // the build method is called here
Restarted app in 1 894ms.
flutter: fetching saved itemNo 3
flutter: item number on build 3
Как инициализировать переменные в Flutter при запуске приложения?