如何从flutter中从异步任务中检索到的数据中将图像加载到卡片中?

Posted

技术标签:

【中文标题】如何从flutter中从异步任务中检索到的数据中将图像加载到卡片中?【英文标题】:How to load image to the Card from data retrieved from async task in flutter? 【发布时间】:2019-11-09 19:15:15 【问题描述】:

我是 Flutter 开发的新手。我需要根据通过异步任务加载的数据将图像加载到卡中。

我有一个异步任务,它返回从 sqlite 本地数据库中查询的 Future> 用户数据。使用检索到的数据,我构建了一个 ListView 来显示使用 Card 的用户。但是在卡片内部,我试图显示一个图像,该图像将从 Firebase 存储中下载,具体取决于从本地数据库中检索到的数据。但图像 URL 为空。

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)))
                              ,
                        ),
                      )
                    ],
                  ),
                );
              ,
            );
        
      ,
    );
  

我希望显示从 firebase 存储下载的图像

【问题讨论】:

【参考方案1】:

这将是我的第一个答案,这里可能有很多方法可以改进我的答案。但我会试一试:实际上,您将不得不在Futures 和Streams 上查找很多内容,因为它在许多应用程序中都是相当重要的一部分。如果您的应用程序需要 Web 上的任何内容,它将需要 Futures,或者它是更大的对应 Stream。在这种情况下,如果您想设置一个可能包含多个图像的 Listview,我会选择 Stream。此外,我会将所有数据库逻辑保存在一个单独的文件中。但是,如果您现在不想过多修改代码,我会使用FutureBuilder。 我已经看到您已经在代码中使用了其中一个。但在这种情况下,请使用:

...

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);
  ,
),

【讨论】:

我能够根据我的情况应用您的解决方案。多谢。这节省了我几天的挣扎。如果有人想知道,我会发布我的代码。【参考方案2】:
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];
            int maxsize = 10e6.round();
            return Card(
              elevation: 8.0,
              margin:
                  new EdgeInsets.symmetric(horizontal: 10.0, vertical: 6.0),
              child: Column(
                children: <Widget>[
                  Stack(
                    children: <Widget>[
                      Container(
                          child: FutureBuilder<dynamic>(
                        future: FirebaseStorage()
                            .ref()
                            .child('employer_logo')
                            .child('00001')
                            .child('google-banner.jpg')
                            .getDownloadURL(),
                        builder: (BuildContext context,
                            AsyncSnapshot<dynamic> snapshot) 
                          if (snapshot.connectionState !=
                              ConnectionState.waiting) 
                            return Image(
                              image: CachedNetworkImageProvider(
                                  snapshot.data.toString()),
                              fit: BoxFit.cover,
                            );
                          
                          else 
                            return Text('Loading image....');
                          

                        ,
                      ),


                      ),
                      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)))
                          ,
                    ),
                  )
                ],
              ),
            );
          ,
        );
    
  ,
);

【讨论】:

以上是关于如何从flutter中从异步任务中检索到的数据中将图像加载到卡片中?的主要内容,如果未能解决你的问题,请参考以下文章

如何在flutter中将标记从firebase(真实数据库)检索到新的google maps api

如何将通过 Timer.periodic 从 API 检索到的数据集成到 Flutter Cubit 项目中

在flutter应用程序中从Firebase检索数据时

如何在flutter中从firebase获取数据

使用异步管道显示从应用程序状态检索到的 Observable 数据

Flutter Firestore 使用异步检索所有文档内容