I try to retrieve the imageLink saved in a Firestore collection of userProfile, but I can’t retrieve the data and it displays the following errors. Does anyone know why this happens and how to fix it?
Error
The following _TypeError was thrown building StreamBuilder<DocumentSnapshot<Object?>>(dirty, state:
_StreamBuilderBaseState<DocumentSnapshot<Object?>, AsyncSnapshot<DocumentSnapshot<Object?>>>#dbdf2):
type 'Null' is not a subtype of type 'Map<String, dynamic>' in type cast**
The relevant error-causing widget was:
StreamBuilder<DocumentSnapshot<Object?>>
StreamBuilder:file:///C:/Users/project/lib/views/profile_page.dart:173:34
When the exception was thrown, this was the stack:
#0 _ProfilePageState.build.<anonymous closure>.<anonymous closure> (package:success_auto/views/profile_page.dart:181:39)
profile_page.dart:181
#1 StreamBuilder.build (package:flutter/src/widgets/async.dart:439:81)
async.dart:439
#2 _StreamBuilderBaseState.build (package:flutter/src/widgets/async.dart:120:48)
async.dart:120
#3 StatefulElement.build (package:flutter/src/widgets/framework.dart:5409:27)
framework.dart:5409
#4 ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:5297:15)
framework.dart:5297
#5 StatefulElement.performRebuild (package:flutter/src/widgets/framework.dart:5462:11)
framework.dart:5462
#6 Element.rebuild (package:flutter/src/widgets/framework.dart:5016:7)
framework.dart:5016
#7 BuildOwner.buildScope (package:flutter/src/widgets/framework.dart:2779:19)
framework.dart:2779
#8 WidgetsBinding.drawFrame (package:flutter/src/widgets/binding.dart:916:21)
binding.dart:916
#9 RendererBinding._handlePersistentFrameCallback (package:flutter/src/rendering/binding.dart:360:5)
binding.dart:360
#10 SchedulerBinding._invokeFrameCallback (package:flutter/src/scheduler/binding.dart:1297:15)
binding.dart:1297
#11 SchedulerBinding.handleDrawFrame (package:flutter/src/scheduler/binding.dart:1227:9)
binding.dart:1227
#12 SchedulerBinding._handleDrawFrame (package:flutter/src/scheduler/binding.dart:1085:5)
binding.dart:1085
#13 _invoke (dart:ui/hooks.dart:170:13)
hooks.dart:170
#14 PlatformDispatcher._drawFrame (dart:ui/platform_dispatcher.dart:401:5)
platform_dispatcher.dart:401
#15 _drawFrame (dart:ui/hooks.dart:140:31)
hooks.dart:140
Code
class ProfilePage extends StatefulWidget {
const ProfilePage({super.key});
@override
State<ProfilePage> createState() => _ProfilePageState();
}
class _ProfilePageState extends State<ProfilePage> {
// Added Part
final FirebaseStorage _storage = FirebaseStorage.instance;
final FirebaseFirestore _firestore = FirebaseFirestore.instance;
// current user
final currentUser = FirebaseAuth.instance.currentUser!;
late String imageUrl;
Future<String> uploadImageToStorage(String childName, Uint8List file) async {
Reference ref = _storage.ref().child(childName);
UploadTask uploadTask = ref.putData(file);
TaskSnapshot snapshot = await uploadTask;
String downloadUrl = await snapshot.ref.getDownloadURL();
print(downloadUrl);
return downloadUrl;
}
Future<String> saveData({
required String id,
required String name,
required Uint8List file,
}) async {
String resp = " Some Error Occurred";
try {
if (name.isNotEmpty) {
String imageUrl = await uploadImageToStorage('profileImage', file);
await _firestore.collection('userProfile').add({
'id': FirebaseAuth.instance.currentUser!.uid,
'name': name,
'imageLink': imageUrl,
});
resp = 'success';
}
} catch (err) {
resp = err.toString();
}
return resp;
}
// edit field
Future<void> editField(String field) async {
String newName = '';
await showDialog(
context: context,
builder: (context) => AlertDialog(
backgroundColor: Colors.grey[900],
title: Text(
'Edit $field',
style: const TextStyle(
color: Colors.white,
),
),
content: TextField(
autofocus: true,
style: const TextStyle(color: Colors.white),
decoration: InputDecoration(
hintText: 'Enter new $field',
hintStyle: const TextStyle(color: Colors.grey),
),
onChanged: (value) {
newName = value;
},
),
actions: [
// cancel button
TextButton(
child: const Text(
'Cancel',
style: TextStyle(color: Colors.white),
),
onPressed: () => Navigator.pop(context),
),
// save button
TextButton(
child: const Text(
'Save',
style: TextStyle(color: Colors.white),
),
onPressed: () => Navigator.of(context).pop(newName),
),
],
),
);
// update profile details in Firebase Firestore
if (newName.trim().isNotEmpty) {
// only update if there is something in the textfield
await FirebaseFirestore.instance
.collection('Users')
.doc(currentUser.email)
.update({field: newName});
}
}
// change image
Uint8List? _image;
// File? image;
void selectImage() async {
Uint8List img = await pickImage(ImageSource.gallery);
setState(() {
_image = img;
print('Image path: $_image');
});
}
void saveProfile() async {
String id;
String resp = await StoreData().saveData(
id: FirebaseAuth.instance.currentUser!.uid,
name: currentUser.email as String,
file: _image!,
);
print(resp);
const SnackBar(
content: Text(
'Save',
style: TextStyle(color: Colors.green),
),
);
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
centerTitle: true,
title: const Text('Profile Page'),
backgroundColor: primaryClr,
),
drawer: const DrawerListBar(),
body: Container(
padding: const EdgeInsets.symmetric(horizontal: 32),
child: StreamBuilder<DocumentSnapshot>(
stream: FirebaseFirestore.instance
.collection('Users')
.doc(currentUser.email)
.snapshots(),
builder: (context, snapshot) {
if (snapshot.hasData) {
final userData = snapshot.data!.data() as Map<String, dynamic>;
return Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Expanded(
child: ListView(
children: [
const SizedBox(height: 20),
Center(
child: StreamBuilder<DocumentSnapshot>(
stream: FirebaseFirestore.instance
.collection('userProfile')
.doc()
.snapshots(),
builder: (context, snapshot) {
if (snapshot.hasData) {
final userPicture = snapshot.data!.data()
as Map<String, dynamic>;
return Stack(
children: [
_image != null
? CircleAvatar(
radius: 64,
backgroundImage: NetworkImage(
userPicture['imageLink']),
)
: const CircleAvatar(
radius: 64,
backgroundImage: NetworkImage(
'https://png.pngitem.com/pimgs/s/421-4212266_transparent-default-avatar-png-default-avatar-images-png.png'),
),
Positioned(
bottom: -10,
left: 80,
child: IconButton(
onPressed: selectImage,
icon: const Icon(Icons.add_a_photo),
),
),
],
);
} else if (snapshot.hasError) {
Get.snackbar(
'Error',
'Error${snapshot.error}',
backgroundColor: Colors.white,
snackPosition: SnackPosition.BOTTOM,
colorText: Colors.black,
icon: const Icon(
Icons.warning_amber_rounded,
color: Colors.red,
),
);
}
return const EmptyContentsAnimationView();
}),
),
const SizedBox(height: 20),
Text(
currentUser.email!,
textAlign: TextAlign.center,
style: const TextStyle(color: Colors.black),
),
const SizedBox(height: 50),
// user details
const Padding(
padding: EdgeInsets.only(left: 25.0),
child: Text(
'My Details',
style: TextStyle(color: Colors.black),
),
),
// username
ProfileTextBox(
text: userData['username'],
sectionName: 'username',
onPressed: () => editField('username'),
),
const SizedBox(height: 50),
TextButton.icon(
onPressed: saveProfile,
icon: const Icon(Icons.save),
label: const Text('Save'),
),
],
),
),
],
);
} else if (snapshot.hasError) {
Get.snackbar(
'Error',
'Error${snapshot.error}',
backgroundColor: Colors.white,
snackPosition: SnackPosition.BOTTOM,
colorText: Colors.black,
icon: const Icon(
Icons.warning_amber_rounded,
color: Colors.red,
),
);
}
return const EmptyContentsAnimationView();
},
),
),
);
}
}
2
Answers
Make sure that the document with the specified ID exists in the Firestore collection.
Before accessing any field, check if the document exists and the field is not null to avoid the error you mentioned.
And you are using "snapshot" identifier for collection("Users") and collection("userProfile").Try to use different identifiers and try again.
Your’e using the null operator (
!
) in your code:And:
The
!
is the issue ifsnapshot.data
isnull
. The ! operator is a null assertion operator in Dart, which tells the compiler that you are certain the value is not null. However, in this case it is.Instead, what you can use is a
?
— which tells that it can benull
:or maybe even instead:
With a
?
instead of!
.See also