Reputation: 81
I am facing the issue of updating profile picture in my Flutter App. I have displayed the current logged in user's details like this :
body: StreamBuilder<Object>(
stream: FirebaseFirestore.instance
.collection('users')
.doc(loggedInUser)
.snapshots(),
builder: (context, snapshot) {
if (!snapshot.hasData) {
return Center(
child: CircularProgressIndicator(),
);
} else if (snapshot.data != null) {
final userData = snapshot.data as DocumentSnapshot;
return Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Container(
decoration: BoxDecoration(
color: Colors.grey[200],
),
width: MediaQuery.of(context).size.width / 1,
height: MediaQuery.of(context).size.width / 2.5,
child: CachedNetworkImage(
imageUrl: '${userData['image']}',
imageBuilder: (context, imageProvider) => Container(
width: 120,
height: 120,
decoration: BoxDecoration(
image: DecorationImage(
fit: BoxFit.cover,
image: imageProvider,
),
),
),
placeholder: (context, url) =>
Center(child: CircularProgressIndicator()),
errorWidget: (context, url, error) => Icon(Icons.error),
),
),
Container(
margin: EdgeInsets.symmetric(horizontal: 10),
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
children: [
SizedBox(height: 40),
Row(
children: [
Padding(
padding: const EdgeInsets.only(left: 10),
child: Text("Name : ",
style: TextStyle(
fontSize: 18,
color: Colors.black54,
fontWeight: FontWeight.w500)),
),
Padding(
padding: const EdgeInsets.fromLTRB(60, 0, 0, 0),
child: Text('${userData['fullName']}',
style: TextStyle(
fontSize: 18,
color: Colors.black54,
fontWeight: FontWeight.w500)),
)
],
),
SizedBox(height: 20),
],
),
),
],
);
} else
return Text('null');
})
And for updating profile picture in a new "Edit Profile" page, the code I wrote are:
postNewProfilePicture(String userid) async {
final ref =
FirebaseStorage.instance.ref().child('users').child(userid + '.jpg');
await ref.putFile(newprofilePic!);
String url = await ref.getDownloadURL();
newUploadedProfilePic = url;
}
ElevatedButton(
style: ElevatedButton.styleFrom(
padding: EdgeInsets.symmetric(
horizontal: 45, vertical: 10),
textStyle: TextStyle(
fontWeight: FontWeight.w500,
color: Colors.white,
fontSize: 15)),
onPressed: () {
postNewProfilePicture(widget.id);
if (_formKey.currentState!.validate()) {
updateUser(widget.id, name, newUploadedProfilePic);
}
Navigator.of(context).pop();
},
child: Text(
'Update',
style: TextStyle(fontSize: 15),
),
),
Future<void> updateUser(id, name, newimage) {
return users
.doc(id)
.update({
'fullName': name,
'image': newimage
})
.then((value) => print('Success'))
.catchError((error) => print('Error: $error'));
}
With these codes, the url of the new image uploaded sometimes is successfully inserted in Firestore but then other times, only receives null instead. In the case of a successful new profile picture, my application only shows the old profile image as well. How can I insert a new image successfully and load it for display?
Upvotes: 0
Views: 603
Reputation: 1371
"update" it's for one field. Use set with option merge true.
Future<void> updateUser(id, name, newimage) {
return users
.doc(id)
.set({
'fullName': name,
'image': newimage
}, SetOptions(merge: true))
.then((value) => print('Success'))
.catchError((error) => print('Error: $error'));
}
Try to add the model MyUser
@immutable
class MyUser {
final String id;
final String fullName;
final String image;
const MyUser({required this.id, required this.fullName, required this.image});
Map<String, dynamic> toMap() {
return {
'id': id,
'fullName': fullName,
'image': image,
};
}
factory MyUser.fromMap(Map<String, dynamic>? map) {
if (map == null) {
return const MyUser(id: "", fullName: "", image: "");
}
return MyUser(
id: map['id'] as String,
fullName: map['fullName'] as String,
image: map['image'] as String,
);
}
}
Then in your stream builder get your image like this
StreamBuilder<MyUser>(
stream: FirebaseFirestore.instance
.collection('users')
.doc(loggedInUser)
.snapshots()
.map((map) => MyUser.fromMap(map.data())),
builder: (context, snapshot) {
final myUser = snapshot.data;
if(myUser == null){
return const Center(
child: CircularProgressIndicator(),
);
}
print(myUser.image);
return Container();
})
Upvotes: 1