Riverpod不需要的小部件重建(我认为)



我试图使用riverpod来存储登录时存储在Firestore中的用户信息。我想要存储的两条信息是用户的手机号码和他订阅的账户。如果这些字段为空,那么用户将看到一个QR阅读器,它应该读取这些信息并将其存储在Firestore中,并在本地更新riverpod

我的用户加载页面如下:我得到了错误setState() or markNeedsBuild() called during build.。为什么呢?我认为这是因为代码在更新构建方法的同时,它仍在构建。但是我对文档的理解是context.read()不应该重新构建小部件。

final subscribedToProvider = ChangeNotifierProvider((_) => SubscribedTo());
final userMobileProvider = ChangeNotifierProvider((_) => UserMobileProvider());
class LandingRouting extends StatelessWidget {
const LandingRouting({Key key}) : super(key: key);
@override
Widget build(BuildContext context) {
User user = context.watch<User>();
if (user == null) return LoginScreen();
return FutureBuilder(
future: FirebaseFirestore.instance.collection('users').doc(user.uid).get(),
builder: (context, AsyncSnapshot<DocumentSnapshot> snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) return Loading();
if (snapshot.hasError)
return AlertDialog(
title: Text('Error loading user'),
content: Text('${snapshot.error.toString}'),
);
else {
Map<String, dynamic> userData = snapshot.data.data();
if (userData['userType'] == 'baqala') {
return Theme(data: baqalaTheme, child: const BaqalaHomeScreen());
} else {
String subscribedTo = userData['subscribedTo'];
String mobile = userData['mobile'];
context.read(userMobileProvider).update(mobile);  // <--
context.read(subscribedToProvider).update(subscribedTo); // <--
return Theme(
data: userTheme,
child: UserHomeScreen(subscribedTo: subscribedTo, userMobile: mobile),
);
}
}
},
);
}
}

在QR页面中,riverpod值为空,尽管firestore值不为空。因此,在前一页中,这些值没有正确地存储在riverpod中。我想这是因为加载页面出现了异常。

我在QR页面内的构建方法如下:

final subscribedToProvider = ChangeNotifierProvider((ref) => SubscribedTo());
final userMobileProvider = ChangeNotifierProvider((ref) => UserMobileProvider());
....
@override
Widget build(BuildContext context) {
return Consumer(
builder: (context, watch, child) {
String sub = watch(subscribedToProvider).subscribedTo;
String mob = watch(userMobileProvider).mobile;
if (sub == null || mob == null) {
return Column(
children: [
Expanded(
flex: 3,
child: QRView(key: qrKey, onQRViewCreated: _onQRViewCreated),
),
Expanded(
flex: 1,
child: Center(
child: (result != null)
? Text('Barcode Type: ${describeEnum(result.format)}   Data: ${result.code}')
: Text(
// 'Scan your code at your baqala to get your hisab history',
'Go to your baqala and request your QR code.n'
'If your baqala has added you as a subscriber, you will be able to seen'
'your account historynn',
style: TextStyle(fontSize: 18),
textAlign: TextAlign.center,
),
),
),
],
);
}
return History2(baqalaUID: sub, mobile: mob);
},
);
}
void _onQRViewCreated(QRViewController controller) {
this.controller = controller;
controller.scannedDataStream.listen(
(scanData) async {
setState(() => result = scanData);
List<String> qrcode = scanData.code.split('-');
context.read(subscribedToProvider).update(qrcode[0]);  // <-- Am I updating correctly
context.read(userMobileProvider).update(qrcode[1]);
await FirebaseFirestore.instance.collection('users').doc(CurrentUser.getCurrentUser().uid).update(
{
'subscribedTo': qrcode[0],
'mobile': qrcode[1],
},
);
},
);
}

我的供应商:

class SubscribedTo extends ChangeNotifier {
String _subscribedTo;
String get subscribedTo => _subscribedTo;
void update(String subscribedTo) {
_subscribedTo = subscribedTo;
notifyListeners();
}
}
class UserMobileProvider extends ChangeNotifier {
String _mobile;
String get mobile => _mobile;
void update(String mobile) {
_mobile = mobile;
notifyListeners();
}
}

您可以在构建方法中读取状态,但不能更改它,因为根ProviderScope正在侦听它。这会导致你的错误。

要纠正它,你应该创建一个firebase实例提供者,并使用提供者之间的依赖关系来更新状态,当你的用户/firebase实例完成加载。

最新更新