Home > Blockchain >  How to solve Invalid argument(s): No host specified in URI file:///Instance of 'Future<Strin
How to solve Invalid argument(s): No host specified in URI file:///Instance of 'Future<Strin

Time:07-28

I'm trying to display images from Firebase storage for that I've done as explain in here firebase storage how to display image

What I've done:

Declare a variable

Future<ListResult>? _futureListResult;

Initialize it inside initState

@override
void initState() {
  _futureListResult = getInstructorDocument();
  super.initState();
}

Create a method to get value for the initialized variable

Future<ListResult> getInstructorDocument() async {
  final documentViewModel = Provider.of<DocumentViewModel>(context, listen: false);
  ListResult listResult = await documentViewModel.listFile(user!.uid);
  return listResult;
}

Here is the full code

DocumentPicker:

import 'dart:async';
import 'dart:io';

import 'package:file_picker/file_picker.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:firebase_storage/firebase_storage.dart';
import 'package:flutter/material.dart';
import 'package:app_test/provider/document_view_model.dart';
import 'package:path/path.dart' as Path;
import 'package:provider/provider.dart';

import '../constant/color.dart';
import '../constant/text.dart';
import '../model/document.dart';
import '../utils/file_list_controller.dart';
import '../utils/utils.dart';
import 'document_card.dart';
import 'loader.dart';

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

  @override
  State<DocumentPicker> createState() => _DocumentPickerState();
}

class _DocumentPickerState extends State<DocumentPicker> {
  final photoTitleController = TextEditingController();
  File? _file;
  User? user = FirebaseAuth.instance.currentUser;
  List<Document>? documents = [];
  late Document document;
  String extension = "";
  String destination = "";
  final FileListController fileController = FileListController();
  UploadTask? uploadTask;
  Future<ListResult>? _futureListResult;

  @override
  void initState() {
    _futureListResult = getInstructorDocument();
    super.initState();
  }

  //----------------------------------------------------------------------------------------------
  //----------------------------- Free memory allocated to the existing variables ----------------
  //----------------------------------------------------------------------------------------------

  @override
  void dispose() {
    photoTitleController.dispose();
    fileController.controller.close();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    String fileName = _file != null ? Path.basename(_file!.path) : noFileSelectedText;
    print("Doc list 1: $documents");

    return Column(
      children: [
        Row(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            //----------------------------- Pick file from device --------------
            TextButton.icon(
              onPressed: () {
                _clickOnAddFile();
              },
              icon: const Icon(
                Icons.attach_file,
                size: 30,
                color: googleButtonTextColor,
              ),
              label: const Text(
                addFile,
                style: TextStyle(
                  fontSize: 18,
                  color: googleButtonTextColor,
                ),
              ),
            ),
            //----------------------------- Validate picked file ---------------
            TextButton.icon(
              onPressed: () async {
                await _clickOnValidate();
                _clearPhotoTitleTextField();
              },
              icon: const Icon(
                Icons.cloud_upload,
                size: 30,
                color: googleButtonTextColor,
              ),
              label: const Text(
                upload,
                style: TextStyle(
                  fontSize: 18,
                  color: googleButtonTextColor,
                ),
              ),
            ),
          ],
        ),
        //----------------------------- Picked file default name ---------------
        Row(
          children: [
            Expanded(
              child: Text(
                fileName,
                style: const TextStyle(
                  fontSize: 16,
                  fontWeight: FontWeight.bold,
                  color: black,
                ),
                overflow: TextOverflow.ellipsis,
                maxLines: 1,
              ),
            ),
            uploadTask != null
            ? loadingStatus(uploadTask!)
            : Container(),
          ],
        ),
        const SizedBox(height: 10,),
        //----------------------------- Picked file title ----------------------
        TextField(
          controller: photoTitleController,
          cursorColor: cursorColor,
          textInputAction: TextInputAction.next,
          decoration: InputDecoration(
            prefixIcon: const Icon(
              Icons.edit,
              color: grey,
              size: 30,
            ),
            enabledBorder: OutlineInputBorder(
              borderSide: const BorderSide(color: Colors.grey),
              borderRadius: BorderRadius.circular(5.5),
            ),
            focusedBorder: OutlineInputBorder(
              borderSide: const BorderSide(color: Colors.orange),
              borderRadius: BorderRadius.circular(5.5),
            ),
            labelText: fileTitleText,
          ),
        ),
        const SizedBox(height: 10,),
        //----------------------------- Show list of picked file ---------------
        FutureBuilder(
            future: _futureListResult,//documentViewModel.listFile(user!.uid),
            builder: (context, AsyncSnapshot<ListResult> snapshot) {
              if(snapshot.connectionState == ConnectionState.done && snapshot.hasData) {
                return ListView.builder(
                    itemCount: snapshot.data!.items.length,
                    itemBuilder: (context, index) {
                      final photo = snapshot.data!.items[index].getDownloadURL(); // <---------- Problem with this
                      final photoName = snapshot.data!.items[index].name;

                      print("Photo: $photo");
                      print("PhotoName: $photoName");
                      return Row(
                        children: [
                          Container(
                            width: 100,
                            height: 100,
                            child: Image.network(
                              fit: BoxFit.cover,
                              photo.toString(), // <--------------------------------------
                              /*errorBuilder: (context, exception, stackTrace) {
                                return Container(
                                  color: grey,
                                  width: 100,
                                  height: 100,
                                  child: const Center(
                                    child: Text(
                                      errorLoadImage,
                                      textAlign: TextAlign.center,
                                    ),
                                  ),
                                );
                              },*/
                            ),
                          ),
                          const SizedBox(width: 20,),
                          Container(
                            width: 50,
                            height: 50,
                            child: Text(
                              /*snapshot.data!.items[index].name.contains(".jpeg")
                              || snapshot.data!.items[index].name.contains(".jpg")
                              || snapshot.data!.items[index].name.contains(".png")
                              || snapshot.data!.items[index].name.contains(".pdf")
                              ? ""
                              : */photoName,
                            ),
                          ),
                        ],
                      );
                    },
                    shrinkWrap: true,
                    physics: const BouncingScrollPhysics(),
                  );
              }
              if(snapshot.connectionState == ConnectionState.waiting || !snapshot.hasData) {
                return const Loader();
              }
              if(snapshot.hasError) {
                return Utils.showErrorMessage(snapshot.hasError.toString());
              }
              return Container();
            },
        ),
      ],
    );
  }

  //----------------------------------------------------------------------------
  //----------------------------- Get instructor document ----------------------
  //----------------------------------------------------------------------------

  Future<ListResult> getInstructorDocument() async {
    final documentViewModel = Provider.of<DocumentViewModel>(context, listen: false);
    ListResult listResult = await documentViewModel.listFile(user!.uid);
    return listResult;
  }

  //----------------------------------------------------------------------------
  //----------------------------- Pick file from device ------------------------
  //----------------------------------------------------------------------------

  Future _clickOnAddFile() async{
    final result = await FilePicker.platform.pickFiles(
        allowMultiple: false,
        type: FileType.custom,
        allowedExtensions: ["jpg", "jpeg", "png", "pdf"],
    );

    if(result == null) return;

    final path = result.files.single.path!;
    extension = result.files.first.extension!;

    setState(() => _file = File(path));
  }

  //----------------------------------------------------------------------------
  //----------------------------- Validate picked file -------------------------
  //----------------------------------------------------------------------------

  Future _clickOnValidate() async {
    if(_file == null) return;

    final defaultName = Path.basename(_file!.path);
    final fileName = photoTitleController.text.trim();
    destination = "instructorDocuments/${user!.uid}/$fileName";

    document = Document(_file, fileName);
    documents?.add(document);
    fileController.inputFileList.add(documents);

    if(fileName.isEmpty) {
      destination = "instructorDocuments/${user!.uid}/$defaultName";
      uploadTask = DocumentViewModel.uploadInstructorDocument(destination, _file!);
      setState((){});
    }
    else {
      uploadTask = DocumentViewModel.uploadInstructorDocument(destination, _file!);
      setState((){});
    }
  }

  //----------------------------------------------------------------------------
  //----------------------------- Clear photo title text field -----------------
  //----------------------------------------------------------------------------

  _clearPhotoTitleTextField() {
    photoTitleController.clear();
  }

  //----------------------------------------------------------------------------
  //----------------------------- Loading status percentage --------------------
  //----------------------------------------------------------------------------

  Widget loadingStatus(UploadTask uploadTask) => StreamBuilder<TaskSnapshot>(
      stream: uploadTask.snapshotEvents,
      builder: (context, snapshot) {
        if(snapshot.hasData){
          final snap = snapshot.data;
          final progress = snap!.bytesTransferred / snap.totalBytes;
          final percentage = (progress * 100).toStringAsFixed(2);

          return Text(
            "$percentage %",
            style: const TextStyle(
              fontSize: 16,
              fontWeight: FontWeight.bold,
            ),
          );
        }
        else {
          return Container();
        }
      },
  );
}

DocumentViewModel:

import 'dart:io';
import 'dart:typed_data';

import 'package:firebase_storage/firebase_storage.dart';
import 'package:flutter/material.dart';
import 'package:app_test/utils/utils.dart';

class DocumentViewModel extends ChangeNotifier {

  //----------------------------------------------------------------------------
  //----------------------------- Upload instructor document -------------------
  //----------------------------------------------------------------------------

  static UploadTask? uploadInstructorDocument(String destination, File file) {
    try {
      final reference = FirebaseStorage.instance
              .ref(destination);
      return reference.putFile(file);
    } on FirebaseException catch (e) {
      return null;
    }
  }

  //----------------------------------------------------------------------------
  //----------------------------- Get instructor document ----------------------
  //----------------------------------------------------------------------------

  Future<ListResult> listFile(String uid) async {
    try {
      ListResult result = await FirebaseStorage.instance
              .ref("instructorDocuments/")
              .child("$uid/")
              .listAll();

      return result;
    } on FirebaseException catch (e) {
      return Utils.showErrorMessage(e.message);
    }
  }

  //----------------------------------------------------------------------------
  //----------------------------- Upload instructor document bytes -------------
  //----------------------------------------------------------------------------

  static UploadTask? uploadBytes(String destination, Uint8List data) {
    try {
      final reference = FirebaseStorage.instance
              .ref(destination);
      return reference.putData(data);
    } on FirebaseException catch (e) {
      return null;
    }
  }
}

What I've tried:

Try #1: Replace with a valid photo Url

Image.network(
        fit: BoxFit.cover,
        "https://www.whysoseriousredux.com/suspects/joker.jpg", // <------------------------- with this it works
),

It means photo is the problem

Try #2: Use a break point to see what kind of data variable will show

final photo = snapshot.data!.items[index].getDownloadURL(); // photo: _Future
final photoName = snapshot.data!.items[index].name; // photoName: "Joker 1"

This confirms that photo is the problem

What am I missing?

Thanks in advance

CodePudding user response:

If we decode Instance of 'Future it becomes Instance of 'Future<String>'. So somewhere in the code you are not calling await on a Future but rather .toString() implicitly or explicitly. And you write yourself:

final photo = snapshot.data!.items[index].getDownloadURL(); // photo: _Future

There you must add await like this:

final photo = await snapshot.data!.items[index].getDownloadURL(); // photo: _Future

CodePudding user response:

@Frank van Puffelen FutureBuilder inside a FutureBuilder was the solution
Thanks for the help. Finally solved the problem with this.

FutureBuilder(
          future: _futureListResult,
          builder: (context, AsyncSnapshot<ListResult> snapshot) {
            if (snapshot.connectionState == ConnectionState.done &&
                snapshot.hasData) {
              return ListView.builder(
                itemCount: snapshot.data!.items.length,
                itemBuilder: (context, index) {
                  final photo = snapshot.data!.items[index].getDownloadURL();
                  final photoName = snapshot.data!.items[index].name;

                  return Row(
                    children: [
                      FutureBuilder(
                        future: photo,
                        builder: (context, AsyncSnapshot<String> snapshot) {
                          if (snapshot.hasData) {
                            final image = snapshot.data;

                            return Image.network(
                              fit: BoxFit.cover,
                              width: 100,
                              height: 100,
                              image!,
                            );
                          }
                          return Container();
                        },
                      ),
                      const SizedBox(
                        width: 20,
                      ),
                      Text(
                        photoName,
                        style: const TextStyle(
                          fontSize: 16,
                          color: black,
                        ),
                      ),
                    ],
                  );
                },
                shrinkWrap: true,
                physics: const BouncingScrollPhysics(),
              );
            }
            if (snapshot.connectionState == ConnectionState.waiting || !snapshot.hasData) {
              return const Loader();
            }
            if (snapshot.hasError) {
              return Utils.showErrorMessage(snapshot.hasError.toString());
            }
            return Container();
          },
        ),
  • Related