Darshan
Darshan

Reputation: 11679

How to display image on screen taken from camera instantly?

Currently I am able to save and retrieve image from firebase storage onto the screen, but the issue I am facing is, if I click picture from camera, it's not showing immediately on the screen (although that image is saved). When I go back to other screen and come back, then the newly taken picture is displayed. But I want to show the image taken from camera instantly on screen. One of the solution from this post is to use Image.file to display local picture and Image.network to display image retrieved from firebase but I am not sure how to use both these conditions to achieve what I am looking for. Below code shows the image downloaded from firebase (inside ClipOval widget)

@override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
          title: Text('Edit Profile'),
          actions: <Widget>[
            new Center(child: new Text('SAVE')),
          ],
        ),
        body: new Stack(
          children: <Widget>[
            Positioned(
              width: 410.0,
              top: MediaQuery
                  .of(context)
                  .size
                  .height / 25,
              child: Column(children: <Widget>[
                Container(
                  child: user.profilePhoto == ""
                      ? Image.file(_imageFile,fit: BoxFit.cover,
                      height: 110.0,
                  width: 110.0,)
                      : ClipOval(
                    child: _imageUrl == null ? Image.asset('icons/default_profile_icon.png', height: 110.0,)
                    :Image.network(_imageUrl,fit: BoxFit.cover,
                    width: 110.0,
                    height: 110.0,)
                  ),
                ),

And this is how I am trying to display the image on screen after clicking picture from camera and then uploading it in firebase:

//display image selected from camera
  imageSelectorCamera() async {
    Navigator.pop(context);
    var imageFile = await ImagePicker.pickImage(
      source: ImageSource.camera,
    );
    setState(() {
      _imageFile = imageFile;
    });

    uploadFile(imageFile);
  }

// Uploads image to firebase storage
  Future<String> uploadFile(imageFile) async {
    String fileName = 'images/profile_pics/' + this.firebaseUser.uid + ".jpeg";
    StorageReference reference = FirebaseStorage.instance.ref().child(fileName);
    StorageUploadTask uploadTask = reference.putFile(imageFile);

    var downloadUrl = await (await uploadTask.onComplete).ref.getDownloadURL();
    String url = downloadUrl.toString();
    return url;

  }

Upvotes: 0

Views: 956

Answers (1)

magicleon94
magicleon94

Reputation: 5182

Your uploadFile returns a string which is not used by anything, or at least this is what I got by reading your code.

Assuming _imageUrl is your state variable for the download URL, just

String resultString = await uploadFile(imageFile);

setState((){
    _imageUrl = resultString;
});

If I understood what you're trying to do and your code, this should help.

You should trigger a change of state when your uploadFile returns the string and use that to rebuild the widget.

By the way, I suggest you to take a look to StreamBuilder, which allow you to build (and rebuild) widgets according to a stream of data (you're using Firebase, I can tell you from experience that Firebase with StreamBuilder is quite awesome and fast).

If you are interested, check this medium article and the docs!

You can find an example of building an app with Firebase Firestore and StreamBuilder here.

Upvotes: 2

Related Questions