列表为空(颤振)

时间:2021-07-11 01:08:21

标签: list flutter arraylist

我正在 Flutter 中创建一个列表并将其显示在一个列中,当我运行它时它只是空的,当我打印列表时它只打印一个数组

I/flutter (24613): []

我正在使用此代码创建列表:-

 myFunction() {
  return StreamBuilder(
  stream:
      users.orderBy('timestamp', descending: true).limit(30).snapshots(),
builder: (context, snapshot) {
 List<UserList> usersList = [];
    snapshot.data.documents.forEach((doc) {
     User user = User.fromDocument(doc);
       UserList userList = UserList(user);
       usersList.add(userList);
    });
    return Column (children: usersList);
   }
  ),
 }

这是我的用户类:-

class User {

final String id;
final String username;
final String email;
final String photoUrl;


User({
  this.id,
  this.username,
  this.email,
  this.photoUrl,
});

factory User.fromDocument(DocumentSnapshot doc) {
   return User(
   id: doc.data()['id'],
   username: doc.data()['username'],
   email: doc.data()['email'],
   photoUrl: doc.data()['photoUrl'],

    );
  }
}
  

代码没有显示错误,列没有显示,而且当我打印列表的长度时,它显示为零:-

I/flutter (24613): 0
 

可能是什么问题??

7 个答案:

答案 0 :(得分:1)

我想我们需要稍微调整您的一些代码才能使逻辑正常工作。 :)

builder 参数应与 Type 一起指定,否则它将是 dynamic 类型。为了在这种情况下更安全,它将是 QuerySnapshot。所以,

builder: (context, snapshot) 在您的代码中变成

builder: (BuildContext context, AsyncSnapshot<QuerySnapshot> snapshot)

接下来,无需遍历 foreach,您可以尝试如下操作。

snapshot.data.docs.map((document) {     ....    }

snapshot.data.documents 在您的代码中不是获取 Firestore 文档的有效方式。请参考official doc

并且您需要从 widget 返回一个 builder,您已经正确完成了。但是,您错误地将 List<UserList> 传递给 Column,这将期待 List<Widget>

return Column (children: usersList);

在这里我可以看到您正在传递类型为 usersListList<UserList>。因此,您可以将 Column 替换为 ListView 或类似的其他 widget,因为 Column 不支持 scroll

<块引用>

因此,将所有这些点点滴滴结合起来,您将得到以下代码片段。

return StreamBuilder(
  stream: FirebaseFirestore.instance
      .collection('users')
      .orderBy('timestamp', descending: true)
      .limit(30)
      .snapshots(),  // Just for simplicity. 
  builder: (BuildContext context, AsyncSnapshot<QuerySnapshot> snapshot) {
    //When there is no data returned from the firebase.
    if (!snapshot.hasData) {
      return Center(
        child: CircularProgressIndicator(),
      );
    }
    return ListView(
      children: snapshot.data.docs.map((document) {
        return Text("Title: " + document['username']);
      }).toList(),
    );
  },
);  

为简单起见,我返回了 Text 小部件。您可以在那里实现自己的用户界面。

注意:这是基本的工作示例,您需要相应地进行微调,例如使用模型类而不是根据您的要求直接访问。

您的代码

 myFunction() {
  return StreamBuilder(
  stream:
      users.orderBy('timestamp', descending: true).limit(30).snapshots(),
builder: (context, snapshot) {
 List<UserList> usersList = [];
    snapshot.data.documents.forEach((doc) {
     User user = User.fromDocument(doc);
       UserList userList = UserList(user);
       usersList.add(userList);
    });
    return Column (children: usersList);
   }
  ),
 }

答案 1 :(得分:0)

这是因为您必须等待 json 才能真正解析到 dart 模型。第二件事是 forEach 方法是同步的,它不会等待异步操作完成,这就是您的列表为空的原因。

This SO 问题有很多不同的方法可以使列表在 flutter 中异步工作。

答案 2 :(得分:0)

Column 是在获取数据之前显示数据,所以它显示的是空列表。为此,在获取数据后根据您的状态管理类型(提供程序中的“notifylisteners”)使用 setstate,因此通过此屏幕将更新并且列也显示更新列表。

答案 3 :(得分:0)

正如 'Ashutosh patole' 所说,'forEach' 方法不会等待迭代完成。

我认为因为这个原因,虽然你做了一个'usersList',
在“usersList”中构建小部件时没有数据。

要解决此问题,您最好将“forEach”更改为“for”。

void main() async {
  List<String> data = [ 'a', 'b', 'c'];
  List<String> result = [];
  data.forEach((data) async {
    await Future.delayed(Duration(seconds: 1));
    result.add(data);
    });
  print(result);
  await Future.delayed(Duration(seconds: 3));
  print(result);
  
  print('-----------------');
  
  result = [];
  for (var item in data) {
    await Future.delayed(Duration(seconds: 1));
    result.add(item);
  }
  print(result);
  await Future.delayed(Duration(seconds: 3));
  print(result);
}

enter image description here

在您的代码中,您可以进行如下更改。

List<UserList> usersList = [];
for (var doc in snapshot.data.documents) {
    User user = User.fromDocument(doc);
    UserList userList = UserList(user);
    usersList.add(userList);
}

答案 4 :(得分:0)

我不太确定您是如何处理变量范围的。 这是我的最小可重现代码,它可以让您了解如何将项目添加到列表中。

class MyPage extends StatefulWidget {
  @override
  _MyPageState createState() => _MyPageState();
}

class _MyPageState extends State<MyPage> {
  final List<Widget> _list = [FlutterLogo()];

  @override
  void initState() {
    super.initState();

    Timer.periodic(Duration(seconds: 1), (timer) {
      if (timer.tick >= 2) timer.cancel();
      setState(() => _list.add(FlutterLogo()));
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Column(children: _list),
    );
  }
}

答案 5 :(得分:0)

在调用数据之前,检查所有字段:

Firestore Docs

添加print()以查看问题所在

FutureBuilder<DocumentSnapshot>(
      future: users.doc(documentId).get(),
      builder:
          (BuildContext context, AsyncSnapshot<DocumentSnapshot> snapshot) {

        //This
        if (snapshot.hasError) {
          return Text("Something went wrong");
        }

        print(snapshot.data);

        //This
        if (snapshot.hasData && !snapshot.data!.exists) {
          return Text("Document does not exist");
        }

        print(snapshot.data);

        //This
        if (snapshot.connectionState == ConnectionState.done) {
          Map<String, dynamic> data = snapshot.data!.data() as Map<String, dynamic>;
          return Text("Full Name: ${data['full_name']} ${data['last_name']}");
        }

        return Text("loading");
      },
    );

答案 6 :(得分:0)

这是我通常使用的。试试这个!请平衡代码中的括号

    FutureBuilder(
                    future: users.orderBy('timestamp', descending: true).limit(30),
                    builder: (BuildContext context, AsyncSnapshot<List<User>> snapshot) {
                      List<User>ulist=snapshot.data;
                        return ListView.builder(
                          shrinkWrap: true,
                          padding: EdgeInsets.only(top: 25,bottom: 35),
                          itemCount: evlist==null?0:evlist.length,
                          itemBuilder: (BuildContext context, int index) {
                            String evtime=evlist[index].fromdate.substring(11,16);
                            String ontime=evlist[index].fromdate.substring(0,16);
                            return Container(
                              decoration: BoxDecoration(
                                  border: Border.all(width: 1.8,color: Colors.indigo[900]),
                                  borderRadius: BorderRadius.circular(12.0),
                                  color: Colors.grey[200]
                              ),
                              margin:
                              const EdgeInsets.symmetric(horizontal: 18.0, vertical: 4.0),
                              child: ListTile(
                                leading: Icon(Icons.notifications),
                                title: Text(ulist[index].username.toString()),
                                subtitle:Text("next data"),

                              ),
                            );
                          },
                        );