英文:
Dart 3 get doc in collection across a routing system
问题
我正在尝试在我的路由系统中获取Future<>
函数的返回值。
我收到了一个错误:
非空局部变量'page'在使用之前必须被赋值
由我的RouteGenerator
类的返回引发。
我的RouteGenerator.dart
文件:
import 'package:chope_ton_diplome/services/CommonService.dart';
import 'package:flutter/material.dart';
class RouteGenerator {
static Route generate(RouteSettings s) {
Widget page;
CommonService commonService = CommonService();
switch (s.name) {
case RouteConsts.termsScreen:
ArgumentsAuth args = s.arguments as ArgumentsAuth;
commonService.terms.then((terms) =>
page = TermsScreen(email: args.email, terms: terms)
);
break;
default:
page = const Center(
child: Text('La route est inaccessible'),
);
break;
}
return MaterialPageRoute(builder: (context) =>
page);
}
}
供参考,这是我的CommonService
:
import 'package:cloud_firestore/cloud_firestore.dart';
class CommonService {
final FirebaseFirestore firebaseFirestore = FirebaseFirestore.instance;
Future<String> get terms async {
String content = '';
DocumentReference documentReference = firebaseFirestore.collection('commons').doc('terms');
content = (await documentReference.get()).get('content');
return content;
}
}
定义一个调用我的小部件的页面,所以我被阻止了。
请帮忙。感谢您的时间。
英文:
I'm trying to get the return of a Future<>
function across my routing system.
I got an error:
> The non-nullable local variable 'page' must be assigned before it can be used
raised by the return of my class RouteGenerator
.
My RouteGenerator.dart
:
import 'package:chope_ton_diplome/services/CommonService.dart';
import 'package:flutter/material.dart';
class RouteGenerator {
static Route generate(RouteSettings s) {
Widget page;
CommonService commonService = CommonService();
switch (s.name) {
case RouteConsts.termsScreen:
ArgumentsAuth args = s.arguments as ArgumentsAuth;
commonService.terms.then((terms) =>
page = TermsScreen(email: args.email, terms: terms)
);
break;
default:
page = const Center(
child: Text('La route est inaccessible'),
);
break;
}
return MaterialPageRoute(builder: (context) => page);
}
}
For information, this is my CommonService
:
import 'package:cloud_firestore/cloud_firestore.dart';
class CommonService {
final FirebaseFirestore firebaseFirestore = FirebaseFirestore.instance;
Future<String> get terms async {
String content = '';
DocumentReference documentReference = firebaseFirestore.collection('commons').doc('terms');
content = (await documentReference.get()).get('content');
return content;
}
}
Define a page call my widget, so I'm blocked.
Help please. Thanks for your time.
答案1
得分: 2
你的generate()
方法是同步的,因此它会一直执行到使用page
本地变量的return
语句。传递给then()
的继续函数只会在generate()
完成后执行。
在switch
语句中,在default
情况下page
是明确赋值的。但在其他情况下,只有当传递给then()
的函数执行后(即使将来的commonService.terms
已经完成),page
才会被赋值。由于这不会在到达return
之前发生,在这种情况下,page
保持未赋值状态。
你可以通过使用基于commonService.terms
未来的FutureBuilder<T>
来解决这个问题。当这个未来完成时,构建器应返回预期的TermsScreen
。同时,在此期间,它应该提供另一个小部件,例如CircularProgressIndicator
。
case RouteConsts.termsScreen:
ArgumentsAuth args = s.arguments as ArgumentsAuth;
page = FutureBuilder<String>(
future: commonService.terms,
builder: (BuildContext context, AsyncSnapshot<String> snapshot) {
if (snapshot.hasData) {
return TermsScreen(email: args.email, terms: snapshot.data!);
} else {
return /* 一些小部件,直到条款完成 */;
}
}
);
break;
英文:
Your generate()
method is synchronous so it will execute all the way down to the return
statement that's using the page
local variable. Continuation functions passed to then()
will only execute after generate()
has completed.
In the switch statement, page
is definitely assigned in the default
case. But not in the other case where page
will only be assigned a value when the function passed to then()
executes (after the future commonService.terms
completes -- even if the future has completed already). Since that will not happen before return
is reached, in that case, page
remains unassigned.
You can work around this by assigning page
with a FutureBuilder<T>
based on the commonService.terms
future. When this future complete, the builder should return the expected TermsScreen
. In the meantime, it should provide another Widget, eg a CircularProgressIndicator
.
case RouteConsts.termsScreen:
ArgumentsAuth args = s.arguments as ArgumentsAuth;
page = FutureBuilder<String>(
future: commonService.terms,
builder: (BuildContext context, AsyncSnapshot<String> snapshot) {
if (snapshot.hasData) {
return TermsScreen(email: args.email, terms: snapshot.data!);
} else {
return /* some widget shown until terms completes */;
}
}
);
break;
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论