Dart 有没有办法在InitState方法上加载异步数据?
我正在寻找一种在InitState方法上加载异步数据的方法,在构建方法运行之前,我需要一些数据。我使用的是GoogleAuth代码,我需要执行build方法,直到流运行为止 我的initState方法是:Dart 有没有办法在InitState方法上加载异步数据?,dart,flutter,Dart,Flutter,我正在寻找一种在InitState方法上加载异步数据的方法,在构建方法运行之前,我需要一些数据。我使用的是GoogleAuth代码,我需要执行build方法,直到流运行为止 我的initState方法是: @override void initState () { super.initState(); _googleSignIn.onCurrentUserChanged.listen((GoogleSignInAccount account) { set
@override
void initState () {
super.initState();
_googleSignIn.onCurrentUserChanged.listen((GoogleSignInAccount account) {
setState(() {
_currentUser = account;
});
});
_googleSignIn.signInSilently();
}
我将非常感谢您的反馈。方法1:您可以使用StreamBuilder来完成此操作。每当流中的数据发生更改时,将运行builder方法 下面是我的一个示例项目的代码片段:
StreamBuilder<List<Content>> _getContentsList(BuildContext context) {
final BlocProvider blocProvider = BlocProvider.of(context);
int page = 1;
return StreamBuilder<List<Content>>(
stream: blocProvider.contentBloc.contents,
initialData: [],
builder: (context, snapshot) {
if (snapshot.data.isNotEmpty) {
return ListView.builder(itemBuilder: (context, index) {
if (index < snapshot.data.length) {
return ContentBox(content: snapshot.data.elementAt(index));
} else if (index / 5 == page) {
page++;
blocProvider.contentBloc.index.add(index);
}
});
} else {
return Center(
child: CircularProgressIndicator(),
);
}
});
}
您可以创建一个
async
方法,并在initState
@覆盖
void initState(){
super.initState();
WidgetsBinding.instance.addPostFrameCallback((){
_异步方法();
});
}
_asyncMethod()异步{
_googleSignIn.onCurrentUserChanged.listen((GoogleSignInAccount帐户){
设置状态(){
_当前用户=帐户;
});
});
_googleSignIn.signizely();
}
现在使用的是。然后
符号似乎起作用:
// ...
@override
initState() {
super.initState();
myAsyncFunction
// as suggested in the comment
// .whenComplete() {
// or
.then((result) {
print("result: $result");
setState(() {});
});
}
//...
先前的答案
您可以在listen函数中设置一个类似loaded的布尔值,并将其设置为true,当loaded设置为true时,让构建函数返回数据,否则只需抛出一个CircularProgressIndicator
编辑--
我不建议在initState中调用的方法中调用setState。如果在调用setState时(异步操作完成时)未装入小部件,将报告错误。我建议你用包装
为了更好地理解initState中的setState,请查看此答案:
这篇文章将让你了解应用程序何时完成构建方法。因此,您可以在挂载小部件后等待异步方法设置状态:示例代码:
@override
void initState() {
super.initState();
asyncOperation().then((val) {
setState(() {});
print("success");
}).catchError((error, stackTrace) {
print("outer: $error");
});
//or
asyncOperation().whenComplete(() {
setState(() {});
print("success");
}).catchError((error, stackTrace) {
print("outer: $error");
});
}
Future<void> asyncOperation() async {
await ... ;
}
@覆盖
void initState(){
super.initState();
asyncOperation()。然后((val){
setState((){});
打印(“成功”);
}).catchError((错误,堆栈跟踪){
打印(“外部:$error”);
});
//或
asyncOperation()。当完成(){
setState((){});
打印(“成功”);
}).catchError((错误,堆栈跟踪){
打印(“外部:$error”);
});
}
Future asyncOperation()异步{
等待;
}
甜美而简短:
(()异步{
等待你的_方法();
setState((){……这里的任何内容});
})();代码>@覆盖
void initState(){
super.initState();
_userStorage.getCurrentUser().then((用户){
设置状态(){
if(user.isAuthenticated){
Timer.run(){
重定向到();
});
}
});
});
}
无效重定向到(){
Navigator.push(上下文,
MaterialPackageRoute(生成器:(BuildContext上下文)=>new ShopOrders());
}
我来这里是因为我需要在程序启动时从FTP获取一些文件。我的项目是一个颤振桌面应用程序。主线程下载添加到FTP服务器的最后一个文件,对其进行解密并显示加密内容,此方法从initState()调用。我想在GUI显示后在后台下载所有其他文件
上述方法都不起作用。构建一个隔离是相对复杂的
简单的方法是使用“计算”方法:
将从FTP下载所有文件的方法移出类
将其设置为带有int参数的int函数(我不使用int参数或结果)
从initState()方法调用它
通过这种方式,GUI显示,程序在后台下载文件
void initState() {
super.initState();
_retrieveFileList(); // this gets the first file and displays it
compute(_backgroundDownloader, 0); // this gets all the other files so that they are available in the local directory
}
int _backgroundDownloader(int value) {
var i = 0;
new Directory('data').createSync();
FTPClient ftpClient = FTPClient('www.guckguck.de',
user: 'maxmusterman', pass: 'maxmusterpasswort');
try {
ftpClient.connect();
var directoryContent = ftpClient.listDirectoryContent();
// .. here, fileNames list is reconstructed from the directoryContent
for (i = 0; i < fileNames.length; i++) {
var dirName = "";
if (Platform.isLinux)
dirName = 'data/';
else
dirName = r'data\';
var filePath = dirName + fileNames[i];
var myDataFile = new File(filePath);
if (!myDataFile.existsSync())
ftpClient.downloadFile(fileNames[i], File(filePath));
}
} catch (err) {
throw (err);
} finally {
ftpClient.disconnect();
}
return i;
void initState(){
super.initState();
_retrieveFileList();//这将获取并显示第一个文件
compute(_backgroundDownloader,0);//这将获取所有其他文件,以便它们在本地目录中可用
}
int_backgroundDownloader(int值){
var i=0;
新目录('data')。createSync();
FTPClient FTPClient=FTPClient('www.guckguck.de',
用户:“maxmusterman”,密码:“maxmusterpasswort”);
试一试{
ftpClient.connect();
var directoryContent=ftpClient.listDirectoryContent();
//…这里,文件名列表是从directoryContent重建的
对于(i=0;i
在initState
中创建匿名函数,如下所示:
@覆盖
void initState(){
super.initState();
//创建匿名函数:
()异步{
等待执行任务();
设置状态(){
//使用所需的更改更新UI。
});
} ();
}
initState()和build不能是异步的,但是在这些函数中,您可以调用异步的函数,而无需等待该函数您可以创建一个异步方法,并在initState内部调用它
@override
void initState() {
super.initState();
Future.delayed(Duration.zero, () async {
//type your method here
});
}
除非他的调用是同步的和即时的,否则不应该更改任何内容。但是这样就没有异步问题了。在这种情况下,在\u asyncMethod
完成之前执行build
。@diegoveloper使用WidgetsBinding.instance.addPostFrameCallback
而不是@Nae answer?调用setState()是错误的当您初始化状态时,这会导致在加载页面后刷新页面,因为您正在initState中调用异步方法。解决方案只有FutureBuilder()。不,没关系,因为我使用的是WidgetsBinding.instance.addPostFrameCallback @override
void initState() {
super.initState();
asyncInitState(); // async is not allowed on initState() directly
}
void asyncInitState() async {
await yourAsyncCalls();
}
void initState() {
super.initState();
_retrieveFileList(); // this gets the first file and displays it
compute(_backgroundDownloader, 0); // this gets all the other files so that they are available in the local directory
}
int _backgroundDownloader(int value) {
var i = 0;
new Directory('data').createSync();
FTPClient ftpClient = FTPClient('www.guckguck.de',
user: 'maxmusterman', pass: 'maxmusterpasswort');
try {
ftpClient.connect();
var directoryContent = ftpClient.listDirectoryContent();
// .. here, fileNames list is reconstructed from the directoryContent
for (i = 0; i < fileNames.length; i++) {
var dirName = "";
if (Platform.isLinux)
dirName = 'data/';
else
dirName = r'data\';
var filePath = dirName + fileNames[i];
var myDataFile = new File(filePath);
if (!myDataFile.existsSync())
ftpClient.downloadFile(fileNames[i], File(filePath));
}
} catch (err) {
throw (err);
} finally {
ftpClient.disconnect();
}
return i;
@override
void initState() {
super.initState();
Future.delayed(Duration.zero, () async {
//type your method here
});
}