Flutter form builder with Image picker

2.4k Views Asked by At

Im using the package flutter_form_builder to collect data in my application.

In particular i'm using the FormBuilderImagePicker control to allow the user to select a photograph from either the gallery or camera.

Im getting an error after calling the future uploadImage with the then() part. The variable "value" never seems to get populated with anything and i'm assuming the add call fails because imageUrl is null;

I receive the download link just file.

Im expecting the future to complete , adding the download link to a list of strings in the state

return FormBuilderImagePicker(
          name: 'image',
          initialValue: _imageList,
          decoration: InputDecoration(
            labelText: widget.question.title,
          ),
          valueTransformer: (value) {
            return jsonEncode(_imageList.toString());
          },
          onChanged: (text) {
            text.forEach((element) {
              File file = new File(element.path.toString());

              storage
                  .uploadImage(
                      context: context,
                      imageToUpload: file,
                      title: basename(file.path.toString()),
                      requestId: database.currentRequest.id)
                  .then((value) {
                setState(() {
                  //ERROR HERE
                  _imageList.add(value.imageUrl);
                });
              });
            });
          },
          validator: FormBuilderValidators.compose(
              [FormBuilderValidators.required(context)]),
        );

the future

Future<CloudStorageResult> uploadImage(
      {@required BuildContext context,
      @required File imageToUpload,
      @required String title,
      @required String requestId}) async {
    final metadata = SettableMetadata(
        contentType: lookupMimeType(title),
        customMetadata: {'requestId': requestId});

    String url;

    var imageFileName = title;

    final Reference firebaseStorageRef =
        FirebaseStorage.instance.ref().child("images/${title}");

    UploadTask uploadTask = firebaseStorageRef.putFile(imageToUpload, metadata);

    await uploadTask.whenComplete(() async {
      var downloadUrl = await firebaseStorageRef.getDownloadURL();

      return CloudStorageResult(
        imageUrl: downloadUrl,
        imageFileName: imageFileName,
      );
    }).catchError((onError) {
      print(onError);
    });
    return null;
  }

stack trace

D/skia    (25275): ------------------------
D/skia    (25275): Errors:
D/skia    (25275):
W/System  (25275): A resource failed to call release.
I/chatty  (25275): uid=10148(com.powerit.my_docs) FinalizerDaemon identical 1 line
W/System  (25275): A resource failed to call release.
E/flutter (25275): [ERROR:flutter/lib/ui/ui_dart_state.cc(177)] Unhandled Exception: NoSuchMethodError: The getter 'imageUrl' was called on null.
E/flutter (25275): Receiver: null
E/flutter (25275): Tried calling: imageUrl
[38;5;244mE/flutter (25275): #0      Object.noSuchMethod (dart:core-patch/object_patch.dart:51:5)[39;49m
[38;5;248mE/flutter (25275): #1      _DynamicFieldState.build.<anonymous closure>.<anonymous closure>.<anonymous closure>[39;49m
 package:my_docs/widgets/dynamic_field.dart
[38;5;244mE/flutter (25275): #2      State.setState[39;49m
 package:flutter/…/widgets/framework.dart
[38;5;248mE/flutter (25275): #3      _DynamicFieldState.build.<anonymous closure>.<anonymous closure>[39;49m
 package:my_docs/widgets/dynamic_field.dart
[38;5;244mE/flutter (25275): #4      _rootRunUnary (dart:async/zone.dart:1198:47)[39;49m
[38;5;244mE/flutter (25275): #5      _CustomZone.runUnary (dart:async/zone.dart:1100:19)[39;49m
[38;5;244mE/flutter (25275): #6      _FutureListener.handleValue (dart:async/future_impl.dart:143:18)[39;49m
[38;5;244mE/flutter (25275): #7      Future._propagateToListeners.handleValueCallback (dart:async/future_impl.dart:696:45)[39;49m
[38;5;244mE/flutter (25275): #8      Future._propagateToListeners (dart:async/future_impl.dart:725:32)[39;49m
[38;5;244mE/flutter (25275): #9      Future._completeWithValue (dart:async/future_impl.dart:529:5)[39;49m
[38;5;244mE/flutter (25275): #10     _AsyncAwaitCompleter.complete (dart:async-patch/async_patch.dart:40:15)[39;49m
[38;5;244mE/flutter (25275): #11     _completeOnAsyncReturn (dart:async-patch/async_patch.dart:311:13)[39;49m
[38;5;248mE/flutter (25275): #12     CloudStorageService.uploadImage (package:my_docs/service/firestore_storage.dart)[39;49m
 package:my_docs/service/firestore_storage.dart
E/flutter (25275): <asynchronous suspension>
[38;5;248mE/flutter (25275): #13     _DynamicFieldState.build.<anonymous closure>[39;49m
 package:my_docs/widgets/dynamic_field.dart
[38;5;244mE/flutter (25275): #14     FormBuilderFieldState.didChange[39;49m
 package:flutter_form_builder/src/form_builder_field.dart
[38;5;244mE/flutter (25275): #15     new FormBuilderImagePicker.<anonymous closure>.<anonymous closure>.<anonymous closure>.<anonymous closure>[39;49m
 package:flutter_form_builder/…/fields/form_builder_image_picker.dart
[38;5;244mE/flutter (25275): #16     _ImageSourceBottomSheetState._onPickImage[39;49m
 package:flutter_form_builder/…/widgets/image_source_sheet.dart
E/flutter (25275): <asynchronous suspension>
[38;5;244mE/flutter (25275): #17     _ImageSourceBottomSheetState.build.<anonymous closure>[39;49m
 package:flutter_form_builder/…/widgets/image_source_sheet.dart
[38;5;244mE/flutter (25275): #18     _InkResponseState._handleTap[39;49m
 package:flutter/…/material/ink_well.dart
[38;5;244mE/flutter (25275): #19     _InkResponseState.build.<anonymous closure>[39;49m
 package:flutter/…/material/ink_well.dart
[38;5;244mE/flutter (25275): #20     GestureRecognizer.invokeCallback[39;49m
 package:flutter/…/gestures/recognizer.dart
[38;5;244mE/flutter (25275): #21     TapGestureRecognizer.handleTapUp[39;49m
 package:flutter/…/gestures/tap.dart
[38;5;244mE/flutter (25275): #22     BaseTapGestureRecognizer._checkUp[39;49m
 package:flutter/…/gestures/tap.dart
[38;5;244mE/flutter (25275): #23     BaseTapGestureRecognizer.acceptGesture[39;49m
 package:flutter/…/gestures/tap.dart
[38;5;244mE/flutter (25275): #24     GestureArenaManager.sweep[39;49m
 package:flutter/…/gestures/arena.dart
[38;5;244mE/flutter (25275): #25     GestureBinding.handleEvent[39;49m
 package:flutter/…/gestures/binding.dart
[38;5;244mE/flutter (25275): #26     GestureBinding.dispatchEvent[39;49m
 package:flutter/…/gestures/binding.dart
[38;5;244mE/flutter (25275): #27     RendererBinding.dispatchEvent[39;49m
 package:flutter/…/rendering/binding.dart
[38;5;244mE/flutter (25275): #28     GestureBinding._handlePointerEvent[39;49m
 package:flutter/…/gestures/binding.dart
[38;5;244mE/flutter (25275): #29     GestureBinding._flushPointerEventQueue[39;49m
 package:flutter/…/gestures/binding.dart
[38;5;244mE/flutter (25275): #30     GestureBinding._handlePointerDataPacket[39;49m
 package:flutter/…/gestures/binding.dart
[38;5;244mE/flutter (25275): #31     _rootRunUnary (dart:async/zone.dart:1206:13)[39;49m
[38;5;244mE/flutter (25275): #32     _CustomZone.runUnary (dart:async/zone.dart:1100:19)[39;49m
[38;5;244mE/flutter (25275): #33     _CustomZone.runUnaryGuarded (dart:async/zone.dart:1005:7)[39;49m
[38;5;244mE/flutter (25275): #34     _invoke1 (dart:ui/hooks.dart:265:10)[39;49m
[38;5;244mE/flutter (25275): #35     _dispatchPointerDataPacket (dart:ui/hooks.dart:174:5)[39;49m
E/flutter (25275):
1

There are 1 best solutions below

0
On

I think you should modify uploadImage method, change await uploadTask.whenComplete to return uploadTask.whenComplete and delete return null;, like this:

Future<CloudStorageResult> uploadImage(
      {@required BuildContext context,
      @required File imageToUpload,
      @required String title,
      @required String requestId}) async {
    final metadata = SettableMetadata(
        contentType: lookupMimeType(title),
        customMetadata: {'requestId': requestId});

    String url;

    var imageFileName = title;

    final Reference firebaseStorageRef =
        FirebaseStorage.instance.ref().child("images/${title}");

    UploadTask uploadTask = firebaseStorageRef.putFile(imageToUpload, metadata);

    return uploadTask.whenComplete(() async {
      var downloadUrl = await firebaseStorageRef.getDownloadURL();

      return CloudStorageResult(
        imageUrl: downloadUrl,
        imageFileName: imageFileName,
      );
    }).catchError((onError) {
      print(onError);
      return null;
    });
  }