#flutter #dart #google-cloud-firestore #flutter-provider #flutter-futurebuilder
#флаттер #dart #google-облако-firestore #flutter-provider #flutter-futurebuilder
Вопрос:
class MyClass extends StatelessWidget {
@override
Widget build(BuildContext context) {
var _userSnapshot;
List<dynamic> myContactsList;
return StreamProvider<DocumentSnapshot>.value(
value: DatabaseService("").myUser,
builder: (context, child) => Expanded(
child: Container(
child: (_userSnapshot = Provider.of<DocumentSnapshot>(context)) ==
null ||
(myContactsList = _userSnapshot.data["contacts"]) == null
? Padding(
// if no contacts were found
padding: EdgeInsets.all(10.0),
child: Column(
children: <Widget>[
Text(
"No recent chats yet",
),
],
),
)
: ListView.builder(
itemCount: _userSnapshot.data["contacts"].length,
itemBuilder: (context, index) => FutureBuilder(
future: DatabaseService("").getUserById(
myContactsList.elementAt(index),
),
builder: (context, snapshot) => GestureDetector(
onTap: () => Navigator.push(
context,
MaterialPageRoute(
builder: (_) => ChatScreen(
myContactsList.elementAt(index),
snapshot.data["displayName"],
),
),
),
child: Container(
margin: EdgeInsets.only(top: 5, bottom: 5, right: 20),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Row(
children: <Widget>[
FutureBuilder(
future: DatabaseService("").getUserById(
myContactsList.elementAt(index),
),
builder: (context, snapshot) =>
CircleAvatar(
radius: 33,
backgroundImage: snapshot
.data["imageUrl"] ==
null
? snapshot.data["isMale"] == true
? AssetImage(
"assets/images/male.png")
: AssetImage(
"assets/images/female.png")
: AssetImage(
"assets/images/male.png"),
),
),
SizedBox(width: 10),
Column(
crossAxisAlignment:
CrossAxisAlignment.start,
children: [
FutureBuilder<DocumentSnapshot>(
future: DatabaseService("").getUserById(
myContactsList.elementAt(index),
),
builder: (context, snapshot) => Text(
snapshot.data["displayName"],
style: TextStyle(
color: Colors.grey,
fontSize: 18,
fontWeight: FontWeight.bold,
),
),
),
SizedBox(height: 5),
Container(
width:
MediaQuery.of(context).size.width *
0.45,
child: Text(
"Something N. $index ",
style: TextStyle(
color: Colors.blueGrey,
fontSize: 18,
fontWeight: FontWeight.w600,
),
overflow: TextOverflow.ellipsis,
),
),
],
),
],
),
Column(
children: <Widget>[
Text(
"TIME"
),
Container(
height: 20,
width: 40,
decoration: BoxDecoration(
color: Theme.of(context).primaryColor,
borderRadius: BorderRadius.circular(30),
),
alignment: Alignment.center,
child: Text(
"NEW",
style: TextStyle(
color: Colors.white,
fontSize: 11,
fontWeight: FontWeight.bold,
),
),
),
],
),
],
),
),
),
),
),
),
),
),
);
}
}
Каждый раз, когда я взаимодействую со своим приложением и запускаю изменение в моей облачной базе данных Firestore, я получаю снимок, используя StreamProvider()
. И когда это происходит, я получаю некоторые исключения, перечисленные ниже, но через полсекунды экран фиксируется, вероятно, из-за нового снимка, я думаю (?).
Как указано ниже, проблема возникает из FutureBuilder()
-за того, что я использую.
Вот ошибка:
The following NoSuchMethodError was thrown building FutureBuilder<DocumentSnapshot>(dirty, state: _FutureBuilderState<DocumentSnapshot>#98dd9):
The method '[]' was called on null.
Receiver: null
Tried calling: []("imageUrl")
The relevant error-causing widget was:
FutureBuilder<DocumentSnapshot> file:///home/pss/Desktop/android/flutter_firebase_chat_app/lib/widgets/recent_chats.dart:90:35
When the exception was thrown, this was the stack:
#0 Object.noSuchMethod (dart:core-patch/object_patch.dart:51:5)
#1 RecentChats.build.<anonymous closure>.<anonymous closure>.<anonymous closure>.<anonymous closure> (package:flutter_firebase_chat_app/widgets/recent_chats.dart:98:56)
#2 _FutureBuilderState.build (package:flutter/src/widgets/async.dart:740:55)
#3 StatefulElement.build (package:flutter/src/widgets/framework.dart:4663:28)
#4 ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:4546:15)
...
════════════════════════════════════════════════════════════════════════════════════════════════════
Another exception was thrown: NoSuchMethodError: The method '[]' was called on null.
════════ Exception caught by widgets library ═══════════════════════════════════════════════════════
The method '[]' was called on null.
Receiver: null
Tried calling: []("displayName")
The relevant error-causing widget was:
FutureBuilder<DocumentSnapshot> file:///home/pss/Desktop/android/flutter_firebase_chat_app/lib/widgets/recent_chats.dart:114:39
Ошибки указывают на эти 2 строки:
backgroundImage: snapshot.data["imageUrl"] == null
amp;
builder: (context, snapshot) => Text(snapshot.data["displayName"]
Так что я не уверен, если честно. Я думаю, что это причина FutureBuilder()
причины, без них я не получаю исключений. Я новичок в Flutter, поэтому буду признателен за любые советы!
Комментарии:
1. Вы пытаетесь вызвать _userSnapshot.data[], но данные равны нулю, сначала вы должны убедиться, что _userSnapshot не равен null, а _userSnapshot . данные тоже
2. я проверю, спасибо, но имейте в виду, что на экране моего телефона будут отображаться желто-черные полосы всего на полсекунды, а затем он каким-то образом правильно отображает изображения.
3. Итак, вам нужно подумать о том, чтобы поместить заполнитель, чтобы не делать его странным, CircularProgressIndicator в качестве start, вы можете использовать библиотеку Shimmer из pub.dev для загрузки некоторых интересных заполнителей (например, facebook)
4. да, я уже думал об этом. Я думаю, это необходимо для некоторых операций! Спасибо
5. так что я не утверждал моментальный снимок. данные и это устраняет проблему, я думаю.
Ответ №1:
Вы пытаетесь вызвать _userSnapshot.data[]
, но data
есть null
, вы должны сначала убедиться, что _userSnapshot
это не null и _userSnapshot.data
тоже.
В то же время, подумайте о том, чтобы поместить загрузчик, который вы можете использовать CircularProgressIndicator
как easy start, или вы можете использовать Shimmer
библиотеку из pub.dev для какой-нибудь классной анимации загрузки заполнителя (например, Facebook).
Ответ №2:
Вы можете установить параметр initialData в StreamProvider, эти данные используются, пока поток еще ничего не выдал. Вы также должны проверить, что _userSnapshot .данные != null перед доступом к одному из его ключей.