我正在尝试将一个简单的 todo 应用程序迁移到 null 安全性和最新的 graphql_flutter 5.0.0 版本。
我正在努力解决空安全部分:我把它做成了 bolt var todo = result.data["todo"]; 在代码块中。
其次,我对graphql_flutter 5.0.0 版本有问题。在代码块中bolt返回缓存;
希望有人可以帮助我吗?
import 'package:flutter/material.dart';
import 'package:graphql_flutter/graphql_flutter.dart';
import '../GraphQLConfig.dart';
String readTodo = """
query(\$id: ID!) {
todo(id: \$id) {
name
done
}
}
""";
String updateTodo = """
mutation updateTodo(\$id: ID!, \$done: Boolean, \$name: String) {
updateTodo(input: { where: { id: \$id }, data: { done: \$done, name: \$name } }) {
todo {
name
done
}
}
}
""";
String deleteTodo = """
mutation deleteTodo(\$id: ID!) {
deleteTodo(input: { where: { id: \$id } }) {
todo {
name
done
}
}
}
""";
class ViewTodo extends StatefulWidget {
final id;
final refresh;
ViewTodo({Key? key, required this.id, this.refresh}) : super(key: key);
@override
ViewTodoState createState() => ViewTodoState(id: id, refresh: this.refresh);
}
class ViewTodoState extends State<ViewTodo> {
final id;
final refresh;
ViewTodoState({Key? key, required this.id, this.refresh});
var editMode = false;
var myController;
bool? done;
@override
Widget build(BuildContext context) {
return GraphQLProvider(
client: GraphQLConfiguration.clientToQuery(),
child: Query(
options: QueryOptions(
document: gql(readTodo),
variables: {'id': id},
pollInterval: Duration(seconds: 0),
),
builder: (QueryResult result,
{VoidCallback? refetch, FetchMore? fetchMore}) {
if (result.hasException) {
return Text(result.exception.toString());
}
if (result.isLoading) {
return Text('Loading');
}
// it can be either Map or List
**var todo = result.data["todo"];**
done = todo["done"];
myController =
TextEditingController(text: todo["name"].toString());
return Scaffold(
appBar: AppBar(
elevation: 0,
automaticallyImplyLeading: false,
backgroundColor: Colors.blue,
flexibleSpace: SafeArea(
child: Container(
padding: EdgeInsets.only(
right: 16, top: 4, bottom: 4, left: 0),
child: Row(children: <Widget>[
IconButton(
onPressed: () {
Navigator.pop(context);
},
icon: Icon(
Icons.arrow_back,
color: Colors.white,
),
),
SizedBox(
width: 20,
),
Text(
"View Todo",
style: TextStyle(
fontSize: 25,
fontWeight: FontWeight.bold,
color: Colors.white),
),
])))),
body: Container(
padding: const EdgeInsets.all(12),
margin: const EdgeInsets.all(8),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(9),
),
width: double.infinity,
child: editMode
? Column(
children: [
Container(
width: double.infinity,
padding: const EdgeInsets.fromLTRB(0, 0, 0, 4),
child: Text("Todo:",
textAlign: TextAlign.left,
style: TextStyle(
color: Colors.black,
fontSize: 20,
))),
TextField(
controller: myController,
decoration: InputDecoration(
border: OutlineInputBorder(),
hintText: 'Add todo'),
),
Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Container(
padding:
const EdgeInsets.fromLTRB(0, 0, 0, 4),
child: Text("Done:",
textAlign: TextAlign.left,
style: TextStyle(
color: Colors.black,
fontSize: 20,
))),
StatefulBuilder(builder:
(BuildContext context,
StateSetter setState) {
return new Checkbox(
value: done,
onChanged: (bool? value) {
print("done:" + done.toString());
setState(() {
done = value;
});
},
);
}),
])
],
)
: Column(
children: [
Container(
width: double.infinity,
padding: const EdgeInsets.fromLTRB(0, 0, 0, 4),
child: Text("Todo:",
textAlign: TextAlign.left,
style: TextStyle(
color: Colors.black,
fontSize: 20,
)),
),
Container(
width: double.infinity,
padding: const EdgeInsets.fromLTRB(0, 0, 0, 4),
child: Text(todo["name"].toString(),
textAlign: TextAlign.left,
style: TextStyle(
color: Colors.black,
fontSize: 30,
fontWeight: FontWeight.bold))),
Container(
width: double.infinity,
padding: const EdgeInsets.fromLTRB(0, 10, 0, 4),
child: Text("Done:",
textAlign: TextAlign.left,
style: TextStyle(
color: Colors.black,
fontSize: 20,
)),
),
Container(
width: double.infinity,
padding: const EdgeInsets.fromLTRB(0, 0, 0, 4),
child: Text(todo["done"].toString(),
textAlign: TextAlign.left,
style: TextStyle(
color: Colors.black,
fontSize: 30,
fontWeight: FontWeight.bold)),
)
],
),
),
floatingActionButton: !editMode
? Mutation(
options: MutationOptions(
document: gql(deleteTodo),
update:
(GraphQLDataProxy cache, QueryResult? result) {
**return cache;**
},
onCompleted: (dynamic resultData) {
print(resultData);
refresh();
ScaffoldMessenger.of(context)
.showSnackBar(SnackBar(content: Text('Done.')));
Navigator.pop(context);
},
),
builder: (
RunMutation runMutation,
QueryResult? result,
) {
return Container(
child: Column(
crossAxisAlignment: CrossAxisAlignment.end,
mainAxisAlignment: MainAxisAlignment.end,
children: [
Padding(
padding: EdgeInsets.fromLTRB(0, 0, 0, 5),
child: FloatingActionButton(
mini: true,
heroTag: null,
child: Icon(Icons.delete),
onPressed: () {
runMutation({'id': id});
ScaffoldMessenger.of(context)
.showSnackBar(SnackBar(
content:
Text('Deleting todo...')));
},
)),
FloatingActionButton(
onPressed: () {
setState(() {
editMode = true;
});
},
tooltip: 'Edit todo',
child: Icon(Icons.edit),
)
]));
})
: Mutation(
options: MutationOptions(
document: gql(updateTodo),
update:
(GraphQLDataProxy cache, QueryResult? result) {
**return scache;**
},
onCompleted: (dynamic resultData) {
print(resultData);
refresh();
refetch!();
ScaffoldMessenger.of(context)
.showSnackBar(SnackBar(content: Text('Done.')));
},
),
builder: (
RunMutation runMutation,
QueryResult? result,
) {
return Container(
child: Column(
crossAxisAlignment: CrossAxisAlignment.end,
mainAxisAlignment: MainAxisAlignment.end,
children: [
Padding(
padding: EdgeInsets.fromLTRB(0, 0, 0, 5),
child: FloatingActionButton(
mini: true,
heroTag: null,
child: Icon(Icons.cancel),
onPressed: () {
setState(() {
editMode = false;
});
},
)),
FloatingActionButton(
heroTag: null,
child: Icon(Icons.save),
onPressed: () {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text('Updating todo...')));
runMutation({
'id': id,
'name': myController.text,
'done': done
});
setState(() {
editMode = false;
});
},
)
]));
}),
);
}));
}
}
收到以下错误:
error • lib/screens/ViewTodo.dart:76:37 • The method '[]' can't be unconditionally invoked because the receiver can be
'null'. Try making the call conditional (using '?.') or adding a null check to the target ('!'). •
unchecked_use_of_nullable_value
error • lib/screens/ViewTodo.dart:263:36 • Undefined name 'scache'. Try correcting the name to one that is defined, or
defining the name. • undefined_identifier