Ad

How To Load Image To The Card From Data Retrieved From Async Task In Flutter?

- 1 answer

I'm new to flutter development. I need to load images into a card depending on data loaded via async task.

I have an async task which returns Future> user data quired from the sqlite local database. With retrieved data, I build a ListView to show users using Card. But inside the card, I'm trying to show an image which will be downloaded from Firebase Storage depending on the data retrieved from the local database. But the image URL is null.

Widget build(BuildContext context) {
    var allCards = DBProvider.db.getAllCards();
    return FutureBuilder<List<User>>(
      future: DBProvider.db.getAllCards(),
      builder: (BuildContext context, AsyncSnapshot<List<User>> snapshot) {
        if (snapshot.hasError) return new Text('Error: ${snapshot.error}');
        switch (snapshot.connectionState) {
          case ConnectionState.waiting:
            return new Text('Loading...');
          default:
            return ListView.builder(
              itemCount: snapshot.data.length,
              itemBuilder: (BuildContext context, int index) {
                User user = snapshot.data[index];
                return Card(
                  elevation: 8.0,
                  margin:
                      new EdgeInsets.symmetric(horizontal: 10.0, vertical: 6.0),
                  child: Column(
                    children: <Widget>[
                      Stack(
                        children: <Widget>[
                          Container(
                            child: Image(
                              image: CachedNetworkImageProvider(FirebaseStorage().ref().child('employer_logo').child('00001').child('google-banner.jpg').getDownloadURL().toString()),
                              fit: BoxFit.cover,
                            ),
                          ),
                          Positioned(
                            bottom: 0,
                            left: 0,
                            child: Container(
                              padding: EdgeInsets.all(10),
                              child: Text(
                                'Google Incorperation',
                                style: TextStyle(
                                    fontSize: 20, color: Colors.white),
                              ),
                            ),
                          )
                        ],
                      ),
                      Container(
                        decoration: BoxDecoration(
                          color: Colors.white10,
                        ),
                        child: ListTile(
                          title: Text(user.fname + " " + user.lname,
                              style: TextStyle(
                                  color: Colors.blue[400], fontSize: 20)),
                          subtitle: Text(user.designation,
                              style: TextStyle(
                                  color: Colors.blue[300], fontSize: 16)),
                          onTap: () => {
                                Navigator.push(
                                    context,
                                    MaterialPageRoute(
                                        builder: (context) => Profile(
                                            user.fname,
                                            user.lname,
                                            user.uid,
                                            user.designation,
                                            user.mobile,
                                            user.employerId)))
                              },
                        ),
                      )
                    ],
                  ),
                );
              },
            );
        }
      },
    );
  }

I expect to show images downloaded from firebase storage

Ad

Answer

This would be my first answer, and there are probably many ways to improve my answer here. But I will give it a go: Actually, you will have to look up a lot on Futuresand Streams, because it is quite a big part in many a app. If your app needs any content on the web, it will need Futures, or it's bigger counterpart Stream. In this case, where you want to set up a Listview with probably multiple images, I would go for a Stream. Also, I would save all my database logic in a seperate file. However, if you don't want to modify your code too much now, I would use a FutureBuilder. I've seen you already use one of them in your code. But in this case, use:

...

int maxsize = 10e6.round(); // This is needed for getData. 10e^6 is usually big enough.
return new Card (
  FutureBuilder<UInt8List> ( // I also think getting Data, instead of a DownloadUrl is more practical here. It keeps the data more secure, instead of generating a DownloadUrl  which is accesible for everyone who knows it. 
  future: FirebaseStorage().ref().child('entire/path/can/go/here')
      .getData(maxsize),
  builder: (BuildContext context, AsyncSnapshot<UInt8List> snapshot) {
      // When this builder is called, the Future is already resolved into snapshot.data
      // So snapshot.data contains the not-yet-correctly formatted Image. 
      return Image.memory(data, fit: BoxFit.Cover);
  },
),
Ad
source: stackoverflow.com
Ad