迁移到空安全:参数类型“对象?”不能分配给参数类型 'List<Widget>'

时间:2021-06-13 02:22:31

标签: flutter flutter-listview flutter-futurebuilder dart-null-safety

在迁移到空安全后,我在 ListView 上收到错误消息“参数类型‘对象?’不能分配给参数类型“列表”。” 我在 return ListView(children: snapshot.data,); 上遇到错误 谁能帮我修复这个错误并在我的应用中为 activityfeeditem 构建一个 ListView?

这是我的 activity_feed.dart 代码,

class ActivityFeed extends StatefulWidget {
@override
_ActivityFeedState createState() => _ActivityFeedState();
}

class _ActivityFeedState extends State<ActivityFeed> {

getActivityFeed() async {
 QuerySnapshot snapshot = await activityFeedRef
     .doc(currentUser!.id)
     .collection('feedItems')
     .orderBy('timestamp', descending: true)
     .limit(50)
     .get();
 List<ActivityFeedItem> feedItems = [];
 snapshot.docs.forEach((doc) {
   feedItems.add(ActivityFeedItem.fromDocument(doc));
   print('Activity Feed Item: ${doc.data}');
 });

 return feedItems;
}

@override
Widget build(BuildContext context) {
 return Scaffold(
   backgroundColor: Colors.deepPurple[50],
   appBar: header(context, titleText: "Activity Feed"),
   body: Container(
     child: FutureBuilder(
       future: getActivityFeed(),
       builder: (context, snapshot) {
         if (!snapshot.hasData) {
           return circularProgress();
         }
         return ListView(
           children: snapshot.data,

// Here I'm getting error on `snapshot.data`

         );
       },
     ),
   ),
 );
}
}

Widget? mediaPreview;
String? activityItemText;

class ActivityFeedItem extends StatelessWidget {
final String? username;
final String? userId;
final String? type; // 'like', 'follow', 'comment'
final String? mediaUrl;
final String? postId;
final String? userProfileImg;
final String? commentData;
final Timestamp? timestamp;

ActivityFeedItem({
 this.username,
 this.userId,
 this.type,
 this.mediaUrl,
 this.postId,
 this.userProfileImg,
 this.commentData,
 this.timestamp,
});

factory ActivityFeedItem.fromDocument(DocumentSnapshot doc) {
 return ActivityFeedItem(
   username: doc['username'],
   userId: doc['userId'],
   type: doc['type'],
   postId: doc['postId'],
   userProfileImg: doc['userProfileImg'],
   commentData: doc['commentData'],
   timestamp: doc['timestamp'],
   mediaUrl: doc['mediaUrl'],
 );
}

showPost(context) {
 Navigator.push(
     context,
     MaterialPageRoute(
         builder: (context) => PostScreen(postId: postId, userId: userId)));
}

configureMediaPreview(context) {
 if (type == "like" || type == 'comment') {
   mediaPreview = GestureDetector(
     onTap: () => showPost(context),
     child: Container(
       height: 50.0,
       width: 50.0,
       child: AspectRatio(
           aspectRatio: 16 / 9,
           child: Container(
             decoration: BoxDecoration(
               image: DecorationImage(
                 fit: BoxFit.cover,
                 image: CachedNetworkImageProvider(mediaUrl!),
               ),
             ),
           )),
     ),
   );
 } else {
   mediaPreview = Text('');
 }

 if (type == 'like') {
   activityItemText = "liked your post";
 } else if (type == 'follow') {
   activityItemText = "is following you";
 } else if (type == 'comment') {
   activityItemText = 'replied: $commentData';
 } else {
   activityItemText = "Error: Unknown type '$type'";
 }
}

@override
Widget build(BuildContext context) {
 configureMediaPreview(context);

 return Padding(
   padding: EdgeInsets.only(bottom: 2.0),
   child: Container(
     color: Colors.white54,
     child: ListTile(
       title: GestureDetector(
         onTap: () => showProfile(context, profileId: userId),
         child: RichText(
           overflow: TextOverflow.ellipsis,
           text: TextSpan(
               style: TextStyle(
                 fontSize: 14.0,
                 color: Colors.black,
               ),
               children: [
                 TextSpan(
                   text: username,
                   style: TextStyle(fontWeight: FontWeight.bold),
                 ),
                 TextSpan(
                   text: ' $activityItemText',
                 ),
               ]),
         ),
       ),
       leading: CircleAvatar(
         backgroundImage: CachedNetworkImageProvider(userProfileImg!),
       ),
       subtitle: Text(
         timeago.format(timestamp!.toDate()),
         overflow: TextOverflow.ellipsis,
       ),
       trailing: mediaPreview,
     ),
   ),
 );
}
}

showProfile(BuildContext context, {String? profileId}) {
Navigator.push(
 context,
 MaterialPageRoute(
   builder: (context) => Profile(
     profileId: profileId,
   ),
 ),
);
}

我尝试了很多方法,但我不知道如何解决这个问题

列表的新代码

Widget build(BuildContext context) {
    return Scaffold(
        backgroundColor: Colors.deepPurple[50],
        appBar: header(context, titleText: "Activity Feed"),
        body: Container(
          child: StreamBuilder<QuerySnapshot>(
              stream: activityFeedRef
                  .doc(currentUser!.id)
                  .collection('feedItems')
                  .orderBy('timestamp', descending: true)
                  .limit(50)
                  .snapshots(),
              builder: (context, snapshot) {
                if (!snapshot.hasData) {
                  return Center(
                    child: circularProgress(),
                  );
                } else
                  return ListView(
                    children: snapshot.data!.docs.map((doc) {
                      return Card(
                        child: ListTile(
                          title: GestureDetector(
                            onTap: () =>
                                showProfile(context, profileId: doc['userId']),
                            child: RichText(
                              overflow: TextOverflow.ellipsis,
                              text: TextSpan(
                                  style: TextStyle(
                                    fontSize: 14.0,
                                    color: Colors.black,
                                  ),
                                  children: [
                                    TextSpan(
                                      text: doc['username'],
                                      style: TextStyle(
                                          fontWeight: FontWeight.bold),
                                    ),
                                    TextSpan(
                                      text: ' $activityItemText',
                                    ),
                                  ]),
                            ),
                          ),
                          leading: CircleAvatar(
                            backgroundImage: CachedNetworkImageProvider(
                                doc['userProfileImg']!),
                          ),
                          subtitle: Text(
                            timeago.format(doc['timestamp']!.toDate()),
                            overflow: TextOverflow.ellipsis,
                          ),
                          trailing: mediaPreview,
                        ),
                      );
                    }).toList(),
                  );
              }),
        ));
  }

2 个答案:

答案 0 :(得分:1)

改变你的getActivityFeed

 Future<List<ActivityFeedItem>>   getActivityFeed() async {
 try{
   QuerySnapshot snapshot = await activityFeedRef
     .doc(currentUser!.id)
     .collection('feedItems')
     .orderBy('timestamp', descending: true)
     .limit(50)
     .get();
 List<ActivityFeedItem> feedItems = [];
 snapshot.docs.forEach((doc) {
   feedItems.add(ActivityFeedItem.fromDocument(doc));
   print('Activity Feed Item: ${doc.data}');
 });

 return feedItems;
}

catch (error) {
   print(error);
   return <ActivityFeedItem>[];
  }}

改变你FutureBuilder如下

FutureBuilder<List<ActivityFeedItem>>(
       future: getActivityFeed(),
       builder: (BuildContextcontext, AsyncSnapshot<List<ActivityFeedItem>> snapshot) {
         if (snapshot.hasError){
          return Center(child: Text("You have an error in loading 
          data"));   
          }
         if (snapshot.hasData) {
           return ListView(
           children: snapshot.data!,
         );
         }
         return CirclularProgressIndicator();

答案 1 :(得分:0)

您也可以使用 as

ListView(
  children: object as List<Widget>,
)