Rex
Rex

Reputation: 313

PickedImage getting null

I want to save an image locally on Device after Picking the Image From Gallery By using Path provider package . but _image file variable gets null after Selecting an Image From Gallery . Thats Why the Screen keeps Stuck on CircularProgressIndicator Screen . Can You Please Help me out of this null _image file variable.

import 'dart:io';
import 'dart:typed_data';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:image_picker/image_picker.dart';
import 'package:path/path.dart';
import 'package:path_provider/path_provider.dart';

class SaveImage extends StatefulWidget {
  const SaveImage({ Key? key }) : super(key: key);

  @override
  _SaveImageState createState() => _SaveImageState();
}

File? _image;


Future<File?> getImage() async{
    var image = File(await ImagePicker.platform
        .pickImage(source: ImageSource.gallery)
        .then((value) => value.path));

final Directory directory = await getApplicationDocumentsDirectory();
final path=directory.toString();
final String fileName = basename(image.path);
// final String fileExtension = extension(image.path);



File newImage = await image.copy('$path/$fileName.jpg');


setState(() {
  _image = newImage;
  
});



  

}

void setState(Null Function() param0) {
}





class _SaveImageState extends State<SaveImage> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: SafeArea(
        child: Center(
          child: Column( 
            children: [
              Text('Pick Image From'),
              SizedBox(height: 30,),
              ElevatedButton(onPressed: (){
                getImage();
              }, child: Text('From Gallery')),
              ElevatedButton(onPressed: (){
               
              }, child: Text('From Camera')),
              SizedBox(height: 50),
              Container(
                child: _image!=null?ClipRRect(
                              borderRadius: BorderRadius.circular(6),
                              child: Image.file(
                                _image!,
                                fit: BoxFit.cover,
                              )):Center(child: CircularProgressIndicator(),)
              ),
            ],
          ),
        ),
      ),
    );
  }
}

Upvotes: 2

Views: 1984

Answers (2)

jeremynac
jeremynac

Reputation: 1242

Some things are wrong in your code:

  1. The getImage() function is not inside your class, so the setState won't work.

  2. You're not checking the return value of ImagePicker.platform.pickImage(), as it can be null. You have to check it before initialising a File with it.

  3. directory.toString() does not return the path of the directory, but it returns "Directory: '/something'". It is meant to be printed. If you want the actual directory path, you need directory.path

  4. If it's still not working, make sure you have done the right setup, as asked by image_picker (setting up your Info.plist for IOS...)

Here is your code, working as expected:

class SaveImage extends StatefulWidget {
  const SaveImage({Key? key}) : super(key: key);

  @override
  _SaveImageState createState() => _SaveImageState();
}

class _SaveImageState extends State<SaveImage> {
  File? _image;

  Future<File?> getImage() async {
      PickedFile? pickedFile =
          await ImagePicker.platform.pickImage(source: ImageSource.gallery);
      if (pickedFile == null) {
        return null;
      }
      final File file = File(pickedFile.path);
      final Directory directory = await getApplicationDocumentsDirectory();
      final path = directory.path;
      final String fileName = basename(pickedFile.path);
// final String fileExtension = extension(image.path);
      File newImage = await file.copy('$path/$fileName');
      setState(() {
        _image = newImage;
      });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: SafeArea(
        child: Center(
          child: Column(
            children: [
              Text('Pick Image From'),
              SizedBox(
                height: 30,
              ),
              ElevatedButton(
                  onPressed: () {
                    getImage();
                  },
                  child: Text('From Gallery')),
              ElevatedButton(onPressed: () {}, child: Text('From Camera')),
              SizedBox(height: 50),
              Container(
                  child: _image != null
                      ? ClipRRect(
                          borderRadius: BorderRadius.circular(6),
                          child: Image.file(
                            _image!,
                            fit: BoxFit.cover,
                          ))
                      : Center(
                          child: CircularProgressIndicator(),
                        )),
            ],
          ),
        ),
      ),
    );
  }
}

If you want to store the image in the cache, you can use flutter_cache_manager library. It allows you to store and retrieve a file in cache.

Here is the code, updated to store the file in cache. Notice that we use a key to identify our file in cache (I set it to the path of the file but you can set it to basically any String as long as it's unique to this file). If you want to use the file app-wide, you would probably need to store the key somewhere that can be accessed there.

class SaveImage extends StatefulWidget {
  const SaveImage({Key? key}) : super(key: key);

  @override
  _SaveImageState createState() => _SaveImageState();
}

class _SaveImageState extends State<SaveImage> {
  File? _image;
  String? cachedFileKey;

  Future<File?> getImage() async {
    PickedFile? pickedFile =
        await ImagePicker.platform.pickImage(source: ImageSource.gallery);
    if (pickedFile == null) {
      return null;
    }
    final File file = File(pickedFile.path);
    final Uint8List fileBytes = await file.readAsBytes();
    final cachedFile = await DefaultCacheManager()
        .putFile(pickedFile.path, fileBytes, key: pickedFile.path);
    setState(() {
      cachedFileKey = pickedFile.path;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: SafeArea(
        child: Center(
          child: Column(
            children: [
              Text('Pick Image From'),
              SizedBox(
                height: 30,
              ),
              ElevatedButton(
                  onPressed: () {
                    getImage();
                  },
                  child: Text('From Gallery')),
              ElevatedButton(onPressed: () {}, child: Text('From Camera')),
              const SizedBox(height: 50),
              Container(
                  child: cachedFileKey != null
                      ? 
                      FutureBuilder<FileInfo?>(future: DefaultCacheManager().getFileFromCache(cachedFileKey!), builder: (context, snapShot) {
                        if (snapShot.hasData && snapShot.data != null) {
                      return ClipRRect(
                          borderRadius: BorderRadius.circular(6),
                          child: Image.file(snapShot.data!.file,
                            fit: BoxFit.cover,
                          ));
                        } else {
                          return const Center(
                          child: CircularProgressIndicator(),
                        );
                        }
                      })
                      : const Center(
                          child: CircularProgressIndicator(),
                        )),
            ],
          ),
        ),
      ),
    );
  }
}

Upvotes: 3

shorol
shorol

Reputation: 1000

use image type PickedFile type. Ex:

PickedFile _image;

  Future pickImageFromGallery(ImageSource source, BuildContext context) async {
    var _image = await ImagePicker.platform.pickImage(source: source);
    image = _image;
 
    _uploadImage(image, context);
  }

**for taking image path:

imageFile.path

Upvotes: 0

Related Questions