Ausgabe
Ich baue die App, die den Baum der miteinander verbundenen Blöcke zurückgeben soll. Ich möchte die Möglichkeit haben, die Informationen zu speichern, nachdem der Benutzer die Änderungen am Telefon vorgenommen hat. Ich verwende dafür getApplicationDocumentsDirectory(), um den Pfad zu erhalten. Nachdem der Benutzer Änderungen vorgenommen und die App geschlossen hat, kann er sie öffnen und seinen gesamten Fortschritt sehen. Also versuche ich die Datei asynchron in initState() zu lesen
Ich habe alles versucht: FutureBuilder; anonyme asynchrone Funktionen in initState; dann; wennVollständig. Ich habe die ganze Zeit das gleiche Ergebnis: Die Informationen werden gelesen, nachdem der Baum erstellt wurde.
Könnt ihr mir dabei helfen? (Mein Code ist unten; Jetzt gibt er einen Typfehler zurück, aber ich weiß nicht, wie ich ihn lösen soll.)
main.dart
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:graphview/GraphView.dart';
import 'dart:math';
import 'MyNode.dart';
void main() {
print("main");
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) => MaterialApp(
home: TreeViewPage(),
);
}
class TreeViewPage extends StatefulWidget {
@override
_TreeViewPageState createState() => _TreeViewPageState();
}
var parsedJson;
final Graph graph = Graph()..isTree = true;
SugiyamaConfiguration builder = SugiyamaConfiguration();
// builder
// ..levelSeparation = (150)
// ..nodeSeparation = (100)
// ..orientation = (SugiyamaConfiguration.ORIENTATION_TOP_BOTTOM);
List<MyNode> ListMyNode = [];
int nodesCount = 0;
String text_from_init_state = "no_data";
class _TreeViewPageState extends State {
@override
Widget build(BuildContext context) {
return Scaffold(
body: FutureBuilder(
future: parsedJson,
builder: (BuildContext context, AsyncSnapshot snapshot) {
if (parsedJson == null) {
return Center(
child: CircularProgressIndicator(
backgroundColor: Colors.red,
valueColor: AlwaysStoppedAnimation<Color>(Colors.blue)),
);
}
return Column(
mainAxisSize: MainAxisSize.max,
children: [
Text(text_from_init_state),
Expanded(
child: InteractiveViewer(
constrained: false,
boundaryMargin: EdgeInsets.all(300),
minScale: 0.01,
maxScale: 5.6,
child: GraphView(
graph: graph,
algorithm: SugiyamaAlgorithm(builder),
paint: Paint()
..color = Colors.green
..strokeWidth = 1
..style = PaintingStyle.stroke,
builder: (Node node) {
// I can decide what widget should be shown here based on the id
var a = node.key!.value as int;
return rectangleWidget(a);
},
),
),
),
],
);
},
),
);
}
Widget rectangleWidget(int a) {
TextEditingController textController = TextEditingController();
if (ListMyNode[a - 1].text != "") {
textController.text = ListMyNode[a - 1].text;
}
return InkWell(
onTap: () {
print("a" + a.toString());
},
child: Container(
padding: EdgeInsets.all(20),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(4),
boxShadow: [
BoxShadow(color: Colors.blue, spreadRadius: 1),
],
),
child: Column(
children: [
Container(
// height: 80,
width: 80,
child: TextField(
keyboardType: TextInputType.multiline,
maxLines: null,
controller: textController,
decoration: const InputDecoration(),
onChanged: (v) async {
await ListMyNode[a - 1].UpdateText(v, ListMyNode);
},
),
),
Container(
alignment: Alignment.bottomRight,
child: IconButton(
icon: Icon(Icons.add_box_rounded),
iconSize: 24,
onPressed: () async {
nodesCount++;
final newNode = Node.Id(nodesCount);
var edge = graph.getNodeAtPosition(a - 1);
graph.addEdge(edge, newNode);
text_from_init_state = await readJson();
setState(() {
MyNode b = MyNode(nodesCount, "");
ListMyNode.add(b);
});
},
),
),
],
),
),
);
}
@override
void initState() {
readJson2().whenComplete(() {
print("PArsed Json: " + parsedJson.toString());
if (parsedJson == "{}") {
final node1 = Node.Id(1);
final node2 = Node.Id(2);
MyNode block0 = MyNode(nodesCount, "empty1");
nodesCount++;
MyNode block1 = MyNode(nodesCount, "empty2");
nodesCount++;
ListMyNode.add(block0);
ListMyNode.add(block1);
graph.addEdge(node1, node2);
} else {
final node1 = Node.Id(1);
final node2 = Node.Id(2);
MyNode block0 = MyNode(nodesCount, parsedJson.toString());
nodesCount++;
MyNode block1 = MyNode(nodesCount, "not_empty2");
nodesCount++;
ListMyNode.add(block0);
ListMyNode.add(block1);
graph.addEdge(node1, node2);
}
print("before setState: " + parsedJson);
setState(() {});
print("after setState: " + parsedJson);
});
super.initState();
builder
..levelSeparation = (150)
..nodeSeparation = (100)
..orientation = (SugiyamaConfiguration.ORIENTATION_TOP_BOTTOM);
}
Future<void> readJson2() async {
try {
final file = await localFile();
// Read the file
final contents = await file.readAsString();
parsedJson = contents;
} catch (e) {
// If encountering an error, return 0
parsedJson = "{}";
}
}
}
MyNode.dart
import 'dart:async';
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:path_provider/path_provider.dart';
String ListMyNodeJSON(List<MyNode> lst) {
Map<int, String> mapMyNodeJSON = {};
for (int i = 0; i < lst.length; i++) {
mapMyNodeJSON[lst[i].id] = lst[i].text;
}
return mapMyNodeJSON.toString();
}
Future<String> localPath() async {
final directory = await getApplicationDocumentsDirectory();
return directory.path;
}
Future<File> localFile() async {
final path = await localPath();
return File('$path/tree.json');
}
Future<File> writeJson(text) async {
final file = await localFile();
return file.writeAsString("$text");
}
Future<String> readJson() async {
try {
final file = await localFile();
// Read the file
final contents = await file.readAsString();
return contents;
} catch (e) {
// If encountering an error, return 0
return "{}";
}
}
class MyNode {
int id = 0;
String text = "";
MyNode(int id, String text) {
this.id = id;
this.text = text;
}
Future<void> UpdateText(String text, List<MyNode> lst) async {
this.text = text;
await writeJson(ListMyNodeJSON(lst));
}
String toString() {
return this.id.toString() + "---" + this.text;
}
}
Lösung
Ich habe Ihren Code aktualisiert, um beim Abrufen von Daten einen Ladebalken anzuzeigen und nach Abschluss Blöcke anzuzeigen. Jetzt erhält es den Fortschritt aus der Datei, aber es scheint, dass Sie die Spiellogik zum Fortsetzen des Fortschritts noch nicht implementiert haben. Ich finde das ein interessantes Projekt. Hoffen Sie, dass dieser Code Ihr Problem löst, und entwickeln Sie den Fortschrittslogikabschnitt weiter.
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:graphview/GraphView.dart';
import 'dart:math';
import 'MyNode.dart';
void main() {
WidgetsFlutterBinding.ensureInitialized();
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) => MaterialApp(
home: TreeViewPage(),
);
}
class TreeViewPage extends StatefulWidget {
@override
_TreeViewPageState createState() => _TreeViewPageState();
}
final Graph graph = Graph()..isTree = true;
SugiyamaConfiguration builder = SugiyamaConfiguration();
// builder
// ..levelSeparation = (150)
// ..nodeSeparation = (100)
// ..orientation = (SugiyamaConfiguration.ORIENTATION_TOP_BOTTOM);
List<MyNode> ListMyNode = [];
int nodesCount = 0;
String text_from_init_state = "no_data";
class _TreeViewPageState extends State {
late String parsedJson;
@override
Widget build(BuildContext context) {
return Scaffold(
body: FutureBuilder(
future: readJson2(),
builder: (BuildContext context, AsyncSnapshot snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) {
return const Center(
child: CircularProgressIndicator(
backgroundColor: Colors.red,
valueColor: AlwaysStoppedAnimation<Color>(Colors.blue)),
);
} else if (snapshot.connectionState == ConnectionState.done) {
parsedJson = snapshot.data as String;
updateNode(parsedJson);
return Column(
mainAxisSize: MainAxisSize.max,
children: [
Text(text_from_init_state),
Expanded(
child: InteractiveViewer(
constrained: false,
boundaryMargin: EdgeInsets.all(300),
minScale: 0.01,
maxScale: 5.6,
child: GraphView(
graph: graph,
algorithm: SugiyamaAlgorithm(builder),
paint: Paint()
..color = Colors.green
..strokeWidth = 1
..style = PaintingStyle.stroke,
builder: (Node node) {
// I can decide what widget should be shown here
//based on the id
var a = node.key!.value as int;
return rectangleWidget(a);
},
),
),
),
],
);
}
return Center(
child: Text(
'Something went wrong!',
style: TextStyle(
color: Colors.red,
),
),
);
},
),
);
}
void updateNode(String parsedReadJson2) {
if (parsedReadJson2.isEmpty) {
final node1 = Node.Id(1);
final node2 = Node.Id(2);
MyNode block0 = MyNode(nodesCount, "empty1");
nodesCount++;
MyNode block1 = MyNode(nodesCount, "empty2");
nodesCount++;
ListMyNode.add(block0);
ListMyNode.add(block1);
graph.addEdge(node1, node2);
} else {
final node1 = Node.Id(1);
final node2 = Node.Id(2);
MyNode block0 = MyNode(nodesCount, parsedReadJson2.toString());
nodesCount++;
MyNode block1 = MyNode(nodesCount, "not_empty2");
nodesCount++;
ListMyNode.add(block0);
ListMyNode.add(block1);
graph.addEdge(node1, node2);
}
}
Widget rectangleWidget(int a) {
TextEditingController textController = TextEditingController();
if (ListMyNode[a - 1].text != "") {
textController.text = ListMyNode[a - 1].text;
}
return InkWell(
onTap: () {
print("a$a");
},
child: Container(
padding: EdgeInsets.all(20),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(4),
boxShadow: [
BoxShadow(color: Colors.blue, spreadRadius: 1),
],
),
child: Column(
children: [
Container(
// height: 80,
width: 80,
child: TextField(
keyboardType: TextInputType.multiline,
maxLines: null,
controller: textController,
decoration: const InputDecoration(),
onChanged: (v) async {
await ListMyNode[a - 1].UpdateText(v, ListMyNode);
},
),
),
Container(
alignment: Alignment.bottomRight,
child: IconButton(
icon: Icon(Icons.add_box_rounded),
iconSize: 24,
onPressed: () async {
nodesCount++;
final newNode = Node.Id(nodesCount);
var edge = graph.getNodeAtPosition(a - 1);
graph.addEdge(edge, newNode);
text_from_init_state = await readJson();
setState(() {
MyNode b = MyNode(nodesCount, "");
ListMyNode.add(b);
});
},
),
),
],
),
),
);
}
@override
void initState() {
super.initState();
builder
..levelSeparation = (150)
..nodeSeparation = (100)
..orientation = (SugiyamaConfiguration.ORIENTATION_TOP_BOTTOM);
}
Future<String> readJson2() async {
try {
final file = await localFile();
// Read the file
final contents = await file.readAsString();
return contents;
} catch (e) {
// If encountering an error, return empty string
return '';
}
}
}
Beantwortet von – Ye Lwin Oo
Antwort geprüft von – Senaida (FixError Volunteer)