带有提供商和持久存储的Flutter应用程序



我一直在试图找出如何构建一个应用程序与持久状态管理器的扑动。我似乎不能使它工作。这是我的带有状态管理器的应用。

我想要存储实际的类,而不仅仅是一个整数,这使得这有点棘手,但是,嘿,这就是我的目标。

import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
void main() {
runApp(
/// Use a provider. Multiprovider works just fine
MultiProvider(
providers: [
ChangeNotifierProvider(create: (_) => State()),
],
child: const MyApp(),
),
);
}
// Define the data type we want to use
// We will use time and value to track data over time
class MyData {
final DateTime time;
final int value;
MyData(this.time, this.value);
}
// Use a state with a change notifier (provider stuff)
class State with ChangeNotifier {
late List<MyData> _dataset = [];
List<MyData> get dataset => _dataset;
State() {
// The dataset is a list of objects
_dataset = [];
}
void addData(time, value) {
// Add data to the dataset
MyData datapoint = MyData(time, value);
_dataset.add(datapoint);
}
void clearData() {
// Clear the dataset
_dataset = [];
}
}
// The actual widget
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return const MaterialApp(
home: MyHomePage(),
);
}
}
class MyHomePage extends StatelessWidget {
const MyHomePage({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Example'),
),
body: Center(
child: Column(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
const Text('You have added this many datapoints'),
const Count(),
IconButton(
onPressed: () =>
context.read<State>().addData(DateTime.now(), 100),
icon: const Icon(Icons.add)),
IconButton(
onPressed: () => context.read<State>().clearData(),
icon: const Icon(Icons.remove))
],
),
),
);
}
}
// And the parsing of the data to a widget
class Count extends StatelessWidget {
const Count({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Text(
/// Calls `context.watch` to make [Count] rebuild when [Counter] changes.
'${context.watch<State>().dataset.length}',
key: const Key('counterState'),
style: Theme.of(context).textTheme.headlineMedium,
);
}
}

问题是。如何在此添加持久逻辑?

持久化数据可以在状态初始化时添加。为了将数据保存在键值存储中,每个对象需要使用json.encodejson.decode之类的字符串化。

这是一个可以工作的更新后的代码片段。

我删除了你的注释,并在添加持久性逻辑的代码中添加了注释。

import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
// Add shared_preferences and convert
import 'package:shared_preferences/shared_preferences.dart';
import 'dart:convert';
void main() {
runApp(
MultiProvider(
providers: [
ChangeNotifierProvider(create: (_) => State()),
],
child: const MyApp(),
),
);
}
class MyData {
final DateTime time;
final int value;
MyData(this.time, this.value);
// Add a converter to from JSON
static MyData fromJSON(Map<String, dynamic> jsonData) {
return MyData(DateTime.fromMillisecondsSinceEpoch(jsonData["time"]),
jsonData["value"]);
}
// Add a converter to from an encoded JSON string
static MyData fromJSONString(String jsonDataString) {
Map<String, dynamic> jsonData = json.decode(jsonDataString);
return MyData.fromJSON(jsonData);
}
// Add a converter to JSON
dynamic toJSON() {
return {"time": time.millisecondsSinceEpoch, "value": value};
}
// Add a converter to JSON string
String toJSONString() {
return json.encode(toJSON());
}
}
class State with ChangeNotifier {
late List<MyData> _dataset = [];
List<MyData> get dataset => _dataset;
State() {
_dataset = [];
// Read the data on the creation of a state
readData();
}
void readData() async {
// Load the data from the shared preferences
final prefs = await SharedPreferences.getInstance();
List<String>? datasetStrings = prefs.getStringList("dataset");
datasetStrings ??= [];
// Load the data into the state
_dataset = datasetStrings
.map((jsonData) => MyData.fromJSONString(jsonData))
.toList();
// Notify the listeners
notifyListeners();
}
void setData() async {
// Load the shared preferences
final prefs = await SharedPreferences.getInstance();
// Load the data into the shared preferences
List<String> datasetStrings =
_dataset.map((dataPoint) => dataPoint.toJSONString()).toList();
await prefs.setStringList("dataset", datasetStrings);
}
void addData(time, value) {
MyData dataPoint = MyData(time, value);
_dataset.add(dataPoint);
// Save the data and notify listeners
setData();
notifyListeners();
}
void clearData() {
_dataset = [];
setData();
notifyListeners();
}
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return const MaterialApp(
home: MyHomePage(),
);
}
}
class MyHomePage extends StatelessWidget {
const MyHomePage({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Example'),
),
body: Center(
child: Column(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
const Text('You have pushed the button this many times:'),
const Count(),
IconButton(
onPressed: () =>
context.read<State>().addData(DateTime.now(), 100),
icon: const Icon(Icons.add)),
IconButton(
onPressed: () => context.read<State>().clearData(),
icon: const Icon(Icons.remove)),
// Also add a refresh button to test
// loading of data without losing debugging connection
IconButton(
onPressed: () => context.read<State>().readData(),
icon: const Icon(Icons.refresh))
],
),
),
);
}
}
class Count extends StatelessWidget {
const Count({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Text(
/// Calls `context.watch` to make [Count] rebuild when [Counter] changes.
'${context.watch<State>().dataset.length}',
key: const Key('counterState'),
style: Theme.of(context).textTheme.headlineMedium,
);
}
}

最新更新