#android #firebase #flutter #google-cloud-firestore #stream-builder
# #Android #firebase #flutter #google-облако-firestore #stream-builder
Вопрос:
Я новичок в flutter. При вызове Settings widget
возникает следующая ошибка. Я пробовал все, что было опубликовано из той же проблемы, но ничего не изменилось. Когда я удаляю StreamBuilder
, он работает нормально. Однако без StreamBuilder
я не могу получить данные из облачного хранилища firestore и отобразить их в виджете настроек.
Вот главный экран, на котором я вызываю Settings widget
.
body: FlatButton.icon(
onPressed: () {
Navigator.of(context)
.push(MaterialPageRoute(builder: (context) => Settings()));
},
icon: Icon(Icons.settings),
label: Text('User Profile')),
);
Вот виджет настроек
import 'dart:math';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flutter/material.dart';
import 'package:flutter_firebase_test/screens/services/auth.dart';
import 'package:flutter_firebase_test/shared/loading.dart';
class Settings extends StatefulWidget {
@override
_Settings createState() => _Settings();
}
class _Settings extends State<Settings> {
AuthService _auth = new AuthService();
@override
Widget build(BuildContext context) {
Color randomColor() {
int index = 0;
List colors = [
Colors.red,
Colors.blue,
Colors.green,
Colors.yellow,
Colors.amber,
Colors.deepPurple
];
Random rnd = new Random();
setState(() => index = rnd.nextInt(6));
return colors[index];
}
return StreamBuilder<QuerySnapshot>(
stream: Firestore.instance.collection('users').snapshots(),
builder: (context, snapshot) {
if (!snapshot.hasData) {
return Loading();
} else {
return Scaffold(
body: Container(
padding: EdgeInsets.fromLTRB(30, 80, 30, 0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Center(
child: Column(
children: [
CircleAvatar(
backgroundColor: randomColor(),
//backgroundImage: AssetImage('assets/avatars/male1.jpg'),
radius: 60,
child: Text(
// TODO: The name will be set later!
"Ali"[0].toUpperCase(),
style: TextStyle(
color: Colors.black,
fontWeight: FontWeight.bold,
fontSize: 40,
),
),
),
SizedBox(
height: 20,
),
Text("dasdas"),
],
),
),
SizedBox(
height: 30,
),
Divider(
color: Colors.black,
),
SizedBox(
height: 40,
),
Wrap(children: [
Text(
"Name:",
style: TextStyle(
fontSize: 20,
),
),
SizedBox(
width: 20,
),
]),
SizedBox(
height: 40,
),
Wrap(children: [
Text(
"Username:",
style: TextStyle(
fontSize: 20,
),
),
SizedBox(
width: 20,
),
Text(
"User fullname will display here",
style: TextStyle(
fontSize: 20,
),
),
]),
],
),
),
);
}
});
}
}
flutter doctor -v
Результат
] Flutter (Channel stable, 1.22.5, on Microsoft Windows [Version 10.0.19042.685], locale en-US)
• Flutter version 1.22.5 at C:srcflutter
• Framework revision 7891006299 (3 weeks ago), 2020-12-10 11:54:40 -0800
• Engine revision ae90085a84
• Dart version 2.10.4
[√] Android toolchain - develop for Android devices (Android SDK version 30.0.2)
• Android SDK at C:UsersdemirAppDataLocalAndroidsdk
• Platform android-30, build-tools 30.0.2
• Java binary at: C:Program FilesAndroidAndroid Studiojrebinjava
• Java version OpenJDK Runtime Environment (build 1.8.0_242-release-1644-b01)
• All Android licenses accepted.
Консоль отладки :
The following assertion was thrown building StreamBuilder<QuerySnapshot>(dirty, state: _StreamBuilderBaseState<QuerySnapshot, AsyncSnapshot<QuerySnapshot>>#778da):
setState() or markNeedsBuild() called during build.
This Settings widget cannot be marked as needing to build because the framework is already in the process of building widgets. A widget can be marked as needing to be built during the build phase only if one of its ancestors is currently building. This exception is allowed because the framework builds parent widgets before children, which means a dirty descendant will always be built. Otherwise, the framework might not visit this widget during this build phase.
state: _StreamBuilderBaseState<QuerySnapshot, AsyncSnapshot<QuerySnapshot>>#778da
The relevant error-causing widget was
StreamBuilder<QuerySnapshot>
package:flutter_firebase_test/…/home/settings.dart:31
When the exception was thrown, this was the stack
#0 Element.markNeedsBuild.<anonymous closure>
package:flutter/…/widgets/framework.dart:4292
#1 Element.markNeedsBuild
package:flutter/…/widgets/framework.dart:4307
#2 State.setState
package:flutter/…/widgets/framework.dart:1264
#3 _Settings.build.randomColor
package:flutter_firebase_test/…/home/settings.dart:27
#4 _Settings.build.<anonymous closure>
package:flutter_firebase_test/…/home/settings.dart:47
...
Ответ №1:
Поместите свой randomColor
метод вне build
метода. Также вам не нужно вызывать setState
вашу индексную переменную, поскольку она локальна в этом методе
Color randomColor() {
int index = 0;
List colors = [
Colors.red,
Colors.blue,
Colors.green,
Colors.yellow,
Colors.amber,
Colors.deepPurple
];
Random rnd = new Random();
index = rnd.nextInt(6);
return colors[index];
}
// ...
@override
Widget build(BuildContext context) {
Комментарии:
1. Ты ужасен. Я боролся с этой ошибкой в течение 2 дней. Большое вам спасибо. Но, поскольку я студент, я хочу спросить, почему я должен перемещать
randomColor
метод за пределы виджета сборки? Что изменилось?2. При каждом вызове setState также вызывается метод сборки. Так что это будет происходить в рекурсивном режиме до тех пор, пока не возникнет ошибка.
3. Если на ваш вопрос получен ответ, пожалуйста, отметьте ответ как правильный и проголосуйте, чтобы помочь будущим читателям
4. Рад, что это помогло! Счастливого кодирования