导航器在异步调用完成按钮点击颤振之前推送一个新页面
Navigator pushes a new page before the async call finishes on button clicked flutter
问题描述
所以我创建了一个应用程序,我试图在用户注册时向 firebase 添加一些数据。所以在我的注册页面上,我有一个注册按钮,它创建了 firebase 用户,将一些数据添加到 firebase,然后切换到主页。
问题是在切换到主页之前它似乎没有等待我的异步操作完成(这稍后会产生几个问题,但这不是重点)。为了得出这个结论,我用延迟打印功能做了几次测试,它证实了我刚才的解释。
请注意,我也尝试使用 then 而不是 async 和 await,但仍然是同样的问题,我已经搜索过类似的问题,但我找不到任何解决方案。
另一个精确度:我在登录时没有出现其他所有问题,所以问题似乎出在注册过程中。
所以我在想是不是我在按钮动作功能上做错了。
我的代码
RoundedButton(
buttonAction: () async {
setState(() {
showSpinner = true;
});
try {
final newUserResult =
await _auth.createUserWithEmailAndPassword(
email: _email,
password: _password,
);
User _user = newUserResult.user;
await _user.updateProfile(displayName: _fullName);
_user = _auth.currentUser;
var test = await _firestore
.collection('users')
.doc(_user.uid)
.collection('assets')
.add({
'name': 'CASH',
'symbol': '$',
'amount': 500.0,
});
print(test.id);
// This is a test, the message is printed once I am already on my homepage
await Future.delayed(const Duration(seconds: 4), () {
print('waiting finished');
});
Navigator.pushReplacementNamed(context, HomePage.id);
print('change done');
} catch (e) {
//TODO use a refractored dialog
print(e);
}
setState(() {
showSpinner = false;
});
},
输出
这是我注册时的输出。但是我认为这主要是由于我在构建主页时遇到的问题,因为在切换页面之前 firebase 更新尚未完成。
我很确定这一点,因为当我在其他页面和这个页面之间切换时,构建它没有任何问题,但只有在我注册时才会出现。
flutter: User is signed in!
flutter: Invalid argument(s)
════════ Exception caught by widgets library ═══════════════════════════════════
The following NoSuchMethodError was thrown building AssetCard(dirty):
The method 'toStringAsFixed' was called on null.
Receiver: null
Tried calling: toStringAsFixed(1)
The relevant error-causing widget was
AssetCard
lib/…/HomeScreens/DashboardScreen.dart:134
When the exception was thrown, this was the stack
#0 Object.noSuchMethod (dart:core-patch/object_patch.dart:51:5)
#1 AssetCard.build
package:crypto_coach/components/AssetCard.dart:35
#2 StatelessElement.build
package:flutter/…/widgets/framework.dart:4701
#3 ComponentElement.performRebuild
package:flutter/…/widgets/framework.dart:4627
#4 Element.rebuild
package:flutter/…/widgets/framework.dart:4343
...
════════════════════════════════════════════════════════════════════════════════
════════ Exception caught by widgets library ═══════════════════════════════════
The method 'toDouble' was called on null.
Receiver: null
Tried calling: toDouble()
The relevant error-causing widget was
LayoutBuilder
lib/…/pieChart/PieChartView.dart:21
════════════════════════════════════════════════════════════════════════════════
flutter: VWLLRnHddf5uJ3s12KMt
flutter: on a fini d'attendre
flutter: Looking up a deactivated widget's ancestor is unsafe.
At this point the state of the widget's element tree is no longer stable.
To safely refer to a widget's ancestor in its dispose() method, save a reference to the ancestor by calling dependOnInheritedWidgetOfExactType() in the widget's didChangeDependencies() method.
[VERBOSE-2:ui_dart_state.cc(177)] Unhandled Exception: setState() called after dispose(): _SignUpScreenState#8db90(lifecycle state: defunct, not mounted)
This error happens if you call setState() on a State object for a widget that no longer appears in the widget tree (e.g., whose parent widget no longer includes the widget in its build). This error can occur when code calls setState() from a timer or an animation callback.
The preferred solution is to cancel the timer or stop listening to the animation in the dispose() callback. Another solution is to check the "mounted" property of this object before calling setState() to ensure the object is still in the tree.
This error might indicate a memory leak if setState() is being called because another object is retaining a reference to this State object after it has been removed from the tree. To avoid memory leaks, consider breaking the reference to this object during dispose().
#0 State.setState.<anonymous closure> (package:flutter/src/widgets/fra<…>
精度不高:“on a fini d'attendre”消息是“waiting finished”函数,我在 post 中更新了它,因为它是法语的,但我的代码中没有。
资产卡代码
import 'package:flutter/material.dart';
import 'package:crypto_coach/constants.dart';
class AssetCard extends StatelessWidget {
AssetCard({this.name, this.symbol, this.amount, this.dollarValue});
final String name;
final String symbol;
final double amount;
final double dollarValue;
@override
Widget build(BuildContext context) {
return SizedBox(
width: 160,
child: Card(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(15.0),
),
margin: EdgeInsets.only(left: 8.0, right: 8.0, top: 8.0, bottom: 20.0),
elevation: 10.0,
child: Padding(
padding: EdgeInsets.all(10.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Expanded(
flex: 3,
child: Text(name,
style: (name == 'CASH') ? kCashName : kCurrencyName),
),
Expanded(
flex: 2,
child: Text(
(((name == 'CASH')
? amount.toStringAsFixed(1)
: amount.toStringAsFixed(2)) +
' ' +
symbol),
style: kCryptoValue,
),
),
Expanded(
flex: 3,
child: Text(
(name != 'CASH')
? ('$' + dollarValue.toStringAsFixed(1))
: '',
style: kdollarValue,
),
),
],
),
),
),
);
}
}
解决方案(更新)
最后的问题是我有一个侦听器在检测到新用户登录时正在做导航,所以数据还没有设置。
(请原谅我的英语不好,我是法国人。)
这段代码看起来不错。
根据我们在评论中的讨论,事实证明您登录的侦听器正在执行导航而不是此代码。
问题描述
所以我创建了一个应用程序,我试图在用户注册时向 firebase 添加一些数据。所以在我的注册页面上,我有一个注册按钮,它创建了 firebase 用户,将一些数据添加到 firebase,然后切换到主页。
问题是在切换到主页之前它似乎没有等待我的异步操作完成(这稍后会产生几个问题,但这不是重点)。为了得出这个结论,我用延迟打印功能做了几次测试,它证实了我刚才的解释。
请注意,我也尝试使用 then 而不是 async 和 await,但仍然是同样的问题,我已经搜索过类似的问题,但我找不到任何解决方案。
另一个精确度:我在登录时没有出现其他所有问题,所以问题似乎出在注册过程中。
所以我在想是不是我在按钮动作功能上做错了。
我的代码
RoundedButton(
buttonAction: () async {
setState(() {
showSpinner = true;
});
try {
final newUserResult =
await _auth.createUserWithEmailAndPassword(
email: _email,
password: _password,
);
User _user = newUserResult.user;
await _user.updateProfile(displayName: _fullName);
_user = _auth.currentUser;
var test = await _firestore
.collection('users')
.doc(_user.uid)
.collection('assets')
.add({
'name': 'CASH',
'symbol': '$',
'amount': 500.0,
});
print(test.id);
// This is a test, the message is printed once I am already on my homepage
await Future.delayed(const Duration(seconds: 4), () {
print('waiting finished');
});
Navigator.pushReplacementNamed(context, HomePage.id);
print('change done');
} catch (e) {
//TODO use a refractored dialog
print(e);
}
setState(() {
showSpinner = false;
});
},
输出
这是我注册时的输出。但是我认为这主要是由于我在构建主页时遇到的问题,因为在切换页面之前 firebase 更新尚未完成。 我很确定这一点,因为当我在其他页面和这个页面之间切换时,构建它没有任何问题,但只有在我注册时才会出现。
flutter: User is signed in!
flutter: Invalid argument(s)
════════ Exception caught by widgets library ═══════════════════════════════════
The following NoSuchMethodError was thrown building AssetCard(dirty):
The method 'toStringAsFixed' was called on null.
Receiver: null
Tried calling: toStringAsFixed(1)
The relevant error-causing widget was
AssetCard
lib/…/HomeScreens/DashboardScreen.dart:134
When the exception was thrown, this was the stack
#0 Object.noSuchMethod (dart:core-patch/object_patch.dart:51:5)
#1 AssetCard.build
package:crypto_coach/components/AssetCard.dart:35
#2 StatelessElement.build
package:flutter/…/widgets/framework.dart:4701
#3 ComponentElement.performRebuild
package:flutter/…/widgets/framework.dart:4627
#4 Element.rebuild
package:flutter/…/widgets/framework.dart:4343
...
════════════════════════════════════════════════════════════════════════════════
════════ Exception caught by widgets library ═══════════════════════════════════
The method 'toDouble' was called on null.
Receiver: null
Tried calling: toDouble()
The relevant error-causing widget was
LayoutBuilder
lib/…/pieChart/PieChartView.dart:21
════════════════════════════════════════════════════════════════════════════════
flutter: VWLLRnHddf5uJ3s12KMt
flutter: on a fini d'attendre
flutter: Looking up a deactivated widget's ancestor is unsafe.
At this point the state of the widget's element tree is no longer stable.
To safely refer to a widget's ancestor in its dispose() method, save a reference to the ancestor by calling dependOnInheritedWidgetOfExactType() in the widget's didChangeDependencies() method.
[VERBOSE-2:ui_dart_state.cc(177)] Unhandled Exception: setState() called after dispose(): _SignUpScreenState#8db90(lifecycle state: defunct, not mounted)
This error happens if you call setState() on a State object for a widget that no longer appears in the widget tree (e.g., whose parent widget no longer includes the widget in its build). This error can occur when code calls setState() from a timer or an animation callback.
The preferred solution is to cancel the timer or stop listening to the animation in the dispose() callback. Another solution is to check the "mounted" property of this object before calling setState() to ensure the object is still in the tree.
This error might indicate a memory leak if setState() is being called because another object is retaining a reference to this State object after it has been removed from the tree. To avoid memory leaks, consider breaking the reference to this object during dispose().
#0 State.setState.<anonymous closure> (package:flutter/src/widgets/fra<…>
精度不高:“on a fini d'attendre”消息是“waiting finished”函数,我在 post 中更新了它,因为它是法语的,但我的代码中没有。
资产卡代码
import 'package:flutter/material.dart';
import 'package:crypto_coach/constants.dart';
class AssetCard extends StatelessWidget {
AssetCard({this.name, this.symbol, this.amount, this.dollarValue});
final String name;
final String symbol;
final double amount;
final double dollarValue;
@override
Widget build(BuildContext context) {
return SizedBox(
width: 160,
child: Card(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(15.0),
),
margin: EdgeInsets.only(left: 8.0, right: 8.0, top: 8.0, bottom: 20.0),
elevation: 10.0,
child: Padding(
padding: EdgeInsets.all(10.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Expanded(
flex: 3,
child: Text(name,
style: (name == 'CASH') ? kCashName : kCurrencyName),
),
Expanded(
flex: 2,
child: Text(
(((name == 'CASH')
? amount.toStringAsFixed(1)
: amount.toStringAsFixed(2)) +
' ' +
symbol),
style: kCryptoValue,
),
),
Expanded(
flex: 3,
child: Text(
(name != 'CASH')
? ('$' + dollarValue.toStringAsFixed(1))
: '',
style: kdollarValue,
),
),
],
),
),
),
);
}
}
解决方案(更新)
最后的问题是我有一个侦听器在检测到新用户登录时正在做导航,所以数据还没有设置。
(请原谅我的英语不好,我是法国人。)
这段代码看起来不错。
根据我们在评论中的讨论,事实证明您登录的侦听器正在执行导航而不是此代码。