I currently work on the profile image page and I try to change the profile picture and store into Firebase Storage and Firebase Firestore. However, each time after I select the image and click save although the image details is saved into Firebase but it will display back the default image when I reload or navigate from other page back to the page? How can I display the image changes permanently each time I change the profile image, I have no idea how to do it, please teach me how to do it and place the code on where, appreaciate your help, thank you.
Profile Page Code:
// ignore_for_file: avoid_print, unused_local_variable, avoid_unnecessary_containers
import 'dart:io';
import 'dart:typed_data';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:firebase_storage/firebase_storage.dart';
import 'package:flutter/material.dart';
import 'package:fyp_version1/light_dark_themes/theme.dart';
import 'package:fyp_version1/models/empty_content_animation_view.dart';
import 'package:fyp_version1/resources/image_utils.dart';
import 'package:fyp_version1/resources/upload_image_data.dart';
import 'package:fyp_version1/widgets/profile_text_box.dart';
import 'package:get/get.dart';
import 'package:image_picker/image_picker.dart';
class ProfilePage extends StatefulWidget {
const ProfilePage({super.key});
@override
State<ProfilePage> createState() => _ProfilePageState();
}
class _ProfilePageState extends State<ProfilePage> {
// current user
final currentUser = FirebaseAuth.instance.currentUser!;
late String imageUrl;
// 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;
});
}
void saveProfile() async {
String id;
String resp = await StoreData().saveData(
id: FirebaseAuth.instance.currentUser!.uid,
name: currentUser.email as String,
file: _image!,
);
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
centerTitle: true,
title: const Text('Profile Page'),
backgroundColor: primaryClr,
),
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: Stack(
children: [
_image != null
? CircleAvatar(
radius: 64,
backgroundImage: MemoryImage(_image!),
)
: 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),
),
),
],
),
),
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();
},
),
),
);
}
}
Upload Image to Storage and Firestore Code:
import 'dart:typed_data';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:firebase_storage/firebase_storage.dart';
final FirebaseStorage _storage = FirebaseStorage.instance;
final FirebaseFirestore _firestore = FirebaseFirestore.instance;
class StoreData {
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();
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;
}
}
Image Utils Code:
// ignore_for_file: no_leading_underscores_for_local_identifiers, avoid_print
import 'package:image_picker/image_picker.dart';
pickImage(ImageSource source) async {
final ImagePicker _imagePicker = ImagePicker();
XFile? _file = await _imagePicker.pickImage(source: source);
if (_file != null) {
return await _file.readAsBytes();
}
print('No Images Selected');
}