I am facing an issue with the state of my Flutter application. A user can pick an image from their gallery using the Image Picker package from pub.dev. That goes smoothly, but I am then trying to save the picked image to local storage, with the help of the Path Provider package.
As demonstrated in this quick gif, you can see that picking an image indeed replaces the old one. However, when leaving the page and navigating back to it, the UI displays the old image instead of the new one.
Here is the code for the profile picture stateful widget:
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:image_picker/image_picker.dart';
import 'package:path_provider/path_provider.dart';
import 'custom_profile_picture.dart';
import 'default_profile_picture.dart';
class ProfilePicture extends StatefulWidget {
const ProfilePicture({
Key? key,
}) : super(key: key);
@override
State<ProfilePicture> createState() => _ProfilePictureState();
}
class _ProfilePictureState extends State<ProfilePicture> {
final ImagePicker _picker = ImagePicker();
XFile? pickedFile;
File? localImage;
@override
void initState() {
super.initState();
loadImage();
}
@override
Widget build(BuildContext context) {
return Column(
children: [
pickedFile != null
? CustomProfilePicture(image: File(pickedFile!.path))
: const DefaultProfilePicture(),
TextButton(
onPressed: pickImage,
child: const Text(
'Change picture',
style: TextStyle(fontSize: 12),
),
),
],
);
}
void pickImage() async {
final XFile? image = await _picker.pickImage(source: ImageSource.gallery);
if (image != null) {
print('New image picked');
setState(() {
pickedFile = image;
});
saveImage(image);
}
}
void saveImage(XFile img) async {
String path = (await getApplicationDocumentsDirectory()).path;
File convertedImg = File(img.path);
String fileName = "profilepicture";
File? localImage = await convertedImg.copy("$path/$fileName");
print("Image was saved under: $path/$fileName");
}
void loadImage() async {
String fileName = "profilepicture";
String path = (await getApplicationDocumentsDirectory()).path;
if (await File("$path/$fileName").exists()) {
print('The image exists. Loading image from:');
print('$path/$fileName');
setState(() {
pickedFile = XFile("$path/$fileName");
});
}
}
}
Here is the code for the Profile page, in which is located the profile picture component:
import 'package:flutter/material.dart';
import 'widgets/profile_picture.dart';
import 'widgets/custom_table.dart';
import 'widgets/about_me_content.dart';
import 'widgets/service_info_content.dart';
class ProfileView extends StatelessWidget {
const ProfileView({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: const Color(0xFFe3e3e3),
appBar: AppBar(
foregroundColor: Colors.blue,
title: const Text(
'Profile view',
style: TextStyle(fontWeight: FontWeight.bold),
),
centerTitle: true,
backgroundColor: Colors.white,
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(30)),
),
body: SingleChildScrollView(
clipBehavior: Clip.none,
physics: const AlwaysScrollableScrollPhysics(),
child: Container(
width: double.infinity,
padding: const EdgeInsets.all(12),
child: Align(
alignment: Alignment.center,
child: Column(
children: [
const ProfilePicture(),
const Text(
'William Dupont',
style: TextStyle(fontSize: 26, fontWeight: FontWeight.bold),
textAlign: TextAlign.center,
),
const SizedBox(height: 20),
CustomTable(tableTitle: 'About me', content: AboutMeContent(),),
const SizedBox(height: 20),
CustomTable(tableTitle: 'My service info', content: ServiceInfoContent(),),
],
),
),
),
),
);
}
}
Any question, let me know.
I have found a fix to this issue.
I evict the image at the current path using the evict method.
Code:
void loadImage() async {
String fileName = "profilepicture";
String path = (await getApplicationDocumentsDirectory()).path;
if (await File("$path/$fileName").exists()) {
print('The image exists. Loading image from:');
print('$path/$fileName');
await FileImage(File('$path/$fileName')).evict();
setState(() {
pickedFile = XFile("$path/$fileName");
});
}
}