Reputation: 21
so i am having trouble saving the users pfp when they navigate to a new section on my application, when the user clicks of from the current tab and comes back the pfp disappears, it kills the path it seems. i want to be able to upload a image as the pfp, and when i navigate to a new section within the application for it to still be there. code below:
import 'dart:io';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter/widgets.dart';
import 'package:image_picker/image_picker.dart';
import 'package:path_provider/path_provider.dart';
import 'package:path/path.dart';
import 'save_pfp.dart';
File? image;
class BuildProfile extends StatefulWidget {
const BuildProfile({super.key});
@override
State<BuildProfile> createState() => _BuildProfileState();
}
class _BuildProfileState extends State<BuildProfile> {
Future getImage() async{
try{
image = (await ImagePicker().pickImage(source: ImageSource.gallery)) as File? ;
if (image == null) return;
final imagePermanent = await saveImagePermanently(image!.path);
setState(() => image = imagePermanent);
} on PlatformException catch (e) {
print('failed to pick image: $e');
}
}
Future<File> saveImagePermanently(String imagePath) async{
final directory = await getApplicationDocumentsDirectory();
final fileName = basename(imagePath);
image = File('${directory.path}/$fileName');
return File(imagePath).copy(image!.path);
}
@override
Widget build(BuildContext context) {
return CircleAvatar(
backgroundColor: Colors.grey.shade400,
backgroundImage: image == null ? null
: FileImage(image!),
radius: 56,
child: Align(
alignment:const Alignment(3.2, 0.73),
child: RawMaterialButton(
onPressed: () {
showModalBottomSheet(context: context,
backgroundColor: Colors.black38,
builder: (context) => Container(
height: 180,
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
const Text('camera',
style: TextStyle(color: Colors.white)),
IconButton(
onPressed: () {
// _getFromCamera;
getImage();
},
icon: const Icon(CupertinoIcons.camera,
size: 26,
color: Colors.white,
)),
IconButton(
// pick from gallery
onPressed:() {
getImage();
I have tried different solutions, but run into the same error.
Upvotes: 1
Views: 127
Reputation: 1619
In my case, I'm using Provider strategy to save the picked photos and consume them whenever I want in whatever code I am, this is how I proceeded:
First, get the photos from the image picker:
void _setImageFromPhone(ImageSource imageSource) async {
final pickedFile = await ImagePicker().pickImage(source: imageSource, imageQuality: 75);
if (pickedFile == null) {
return;
}
log(pickedFile.path);
widget.formModel.addNewPhotos(pickedFile.path);
}
The provider where I save the picked photos:
class FormModel extends ChangeNotifier {
final List<String> _photos = [];
void addNewPhotos(String photo) {
_photos.add(photo);
notifyListeners();
}
//getter for photos
UnmodifiableListView<String> get photos => UnmodifiableListView(_photos);
}
After that you can consume the photos you add wherever you want :
@override
Widget build(BuildContext context) {
return Consumer<FormModel>(
key: formModelConsumerKey,
builder: (
context,
formModel,
child,
) {
return
Row(
children:[
]
)
Container(
height: MediaQuery.of(context).size.width * 0.35,
width: MediaQuery.of(context).size.width * 0.35,
decoration: BoxDecoration(
color: LIGHT_GREEN_COLOR,
borderRadius: const BorderRadius.all(
Radius.circular(10),
),
image: DecorationImage(
image: Image.file(File(formModel.photos.first!)).image,
fit: BoxFit.fill,
),
),
child: SizedBox();
);
}
);
}
Also do not forget to provide your Provider class in the top parent widgets, small example bellow :
return MultiProvider(
providers: [
ChangeNotifierProvider(create: (context) => FormModel()),
],
child: MaterialApp()
)
Upvotes: 1