颤动中的Firebase列表

Posted

技术标签:

【中文标题】颤动中的Firebase列表【英文标题】:Firebase List in flutter 【发布时间】:2021-05-06 15:31:42 【问题描述】:

我实施了一个搜索列表,并咨询了 Firebase。最初,所有注册用户都出现在屏幕上,当我单击其中一个用户时,应用程序会显示另一个屏幕,其中包含该用户的所有数据。当您开始在搜索字段中输入内容时,只会显示与输入文本相关的用户。

但是,出现了一个问题:过滤客户时,只有它出现在屏幕上,当我点击打开客户信息时,应用程序会在总列表中显示第一个用户的信息(不考虑过滤器) )。

我相信这是由于索引,它查看文档在 firebase 中的位置。

如何解决这个问题?谢谢!

body: Column(
        children: <Widget>[
          SizedBox(
              height: 5,
            ),
          TextField(
            controller: _procurarpaciente,
            decoration: InputDecoration(
              border: OutlineInputBorder(), labelText: "Pesquisar paciente",prefixIcon: Icon(Icons.search)
            ),
            onChanged: (val) 
              setState(() 
                nome = val;
              );
            ,
          ),
          Expanded(
            child: StreamBuilder<QuerySnapshot>(
            stream: (nome != "" && nome != null)
            ? Firestore.instance
                .collection('pacientes')
                .where("indexList", arrayContains: nome)
                .snapshots()
            : Firestore.instance.collection("pacientes").snapshots(),
        builder: (context, snapshot) 
          switch(snapshot.connectionState)
                  case ConnectionState.none:
                  case ConnectionState.waiting:
                  return Center(
                    child: Column(
                      mainAxisAlignment: MainAxisAlignment.center,
                      children: <Widget>[
                              Icon(Icons.error_outline),
                              Text("Usuário não encontrado")                                                
                      ],
                    ),
                  );
                  default:
                   // List<DocumentSnapshot> documentos =
                     // snapshot.data.documents;
                    return ListView.builder(
                  itemCount: snapshot.data.documents.length,
                  itemBuilder: (context, index) 
                    DocumentSnapshot data = snapshot.data.documents[index];
                    return ListTile(
                      title: Text(
                        data['nome'],
                            style: TextStyle(
                              fontWeight: FontWeight.w700,
                              fontSize: 16,
                      ),),
                      subtitle:Text(
                        "Quarto: $data['quarto']",
                            style: TextStyle(
                              fontWeight: FontWeight.w700,
                              fontSize: 14,
                      ),),
                      leading:CircleAvatar(
                            backgroundImage: NetworkImage(data['foto']),
                          ),
                     onTap: ()=> 
                       //print(data.documentID),
                       _navegarParaPerfil(context, items[index]),
                       
                          
                    );
                    
 
                  ,
                );
        
        
      ),
          )
        ],
        ),
    

void _navegarParaPerfil(BuildContext context, Paciente paciente) async
    await Navigator.push(context,
     MaterialPageRoute(builder: (context) => TelaPaciente(paciente)),
     );
  

dsdsd

【问题讨论】:

_navegarParaPerfil(context, items[index]) --> items 表示 ? 当我按下所选用户时,我调用类 _navegarParaPerfil(导航到配置文件),将索引作为参数传递 @BalasubramaniSundaram 这个类,打开一个包含所选配置文件信息的屏幕 做完过滤,有没有刷新items collection @BalasubramaniSundaram 我尝试这样做,但即使在列表中显示正确的用户,当点击它时,过滤器也不会应用,并且总是打开列表中的第一个没有过滤器的用户跨度> 【参考方案1】:

第 1 步:

class Employee 
  Employee(this.employeeID, this.employeeName, this.branch, this.designation, this.location,
      this.salary,
      this.reference);

  double employeeID;

  String employeeName;

  String designation;

  String branch;

  String location;

  double salary;

  DocumentReference reference;

  factory Employee.fromSnapshot(DocumentSnapshot snapshot) 
    Employee newEmployee = Employee.fromJson(snapshot.data());
    newEmployee.reference = snapshot.reference;
    return newEmployee;
  

  factory Employee.fromJson(Map<String, dynamic> json) =>
      _employeeFromJson(json);

  Map<String, dynamic> toJson() => _employeeToJson(this);

  @override
  String toString() => 'employeeName $employeeName';

第 2 步:

class EmployeeRepository 
  List<Employee> employees = [];

  final CollectionReference collection =
      FirebaseFirestore.instance.collection('employees');

  Stream<QuerySnapshot> getStream() 
    return collection.snapshots();
  

  Future<DocumentReference> add(Employee employee) 
    var documentReference = collection.add(employee.toJson());
    return documentReference;
  

  update(Employee employee) async 
    collection.doc(employee.reference.id).update(employee.toJson());
  
  
  delete(Employee employee) async 
    collection.doc(employee.reference.id).delete();
  

  fromSnapShot(DocumentSnapshot snapshot) => Employee.fromSnapshot(snapshot);

  Future<List<Employee>> buildData(
      AsyncSnapshot snapshot, String filterKey) async 
    List<Employee> list = [];
    List<Employee> filteredList = [];

    /// Based on the user snapShot, you can convert into the List and return to
    /// the futurebuilder

    await Future.forEach(snapshot.data.docs, (element) async 
      list.add(Employee.fromSnapshot(element));
    ).then((value) 
      if (filterKey != null) 
        filteredList = list
            .where((element) =>
                element.employeeID.toString() == filterKey ||
                element.employeeName == filterKey ||
                element.designation == filterKey ||
                element.branch == filterKey ||
                element.location == filterKey ||
                element.salary.toString() == filterKey)
            .toList();
      
    );

    if (filteredList.isEmpty) 
      return Future<List<Employee>>.value(list);
     else 
      return Future<List<Employee>>.value(filteredList);
    
  

第 3 步:

EmployeeRepository employeeRepository = EmployeeRepository();

  TextEditingController textEditingController = TextEditingController();
  String filteredText = '';

  @override
  Widget build(BuildContext context) 
    return SafeArea(
        child: Scaffold(
            appBar: AppBar(
              title: Text('ListView'),
            ),
            body: StreamBuilder(
              stream: employeeRepository.getStream(),
              builder: (context, snapShot) 
                if (snapShot.data == null ||
                    snapShot.connectionState == ConnectionState.waiting ||
                    snapShot.hasError ||
                    snapShot.data.docs.length == 0) 
                  return Container(
                    child: Center(child: CircularProgressIndicator()),
                  );
                 else 
                  return StatefulBuilder(builder: (context, innerSetState) 
                    return FutureBuilder(
                        future: employeeRepository.buildData(
                            snapShot, filteredText),
                        builder: (context, futureSnapShot) 
                          if (!futureSnapShot.hasData) 
                            return Container(
                              child: Center(child: CircularProgressIndicator()),
                            );
                           else 
                            return Column(
                              children: [
                                TextField(
                                  controller: textEditingController,
                                  decoration: InputDecoration(
                                      icon: Icon(Icons.search),
                                      hintText: 'Search here!'),
                                  onSubmitted: (value) 
                                    innerSetState(() 
                                      filteredText = value;
                                    );
                                  ,
                                  onChanged: (value) 
                                    innerSetState(() 
                                      filteredText = value;
                                    );
                                  ,
                                ),
                                Container(
                                  height: 400,
                                  child: ListView.builder(
                                    itemCount: futureSnapShot.data.length,
                                    itemBuilder: (context, index) 
                                      final Employee employee =
                                          futureSnapShot.data[index];
                                      return ListTile(
                                        title: Text(employee.employeeName),
                                        trailing:
                                            Text('Salary$employee.salary'),
                                        subtitle: Text(employee.designation),
                                        onTap: () 
                                          print(employee.salary);
                                          Navigator.push(
                                              context,
                                              MaterialPageRoute(
                                                  builder: (context) =>
                                                      EmployeeDetailsPage(
                                                          employee)));
                                        ,
                                      );
                                    ,
                                  ),
                                ),
                              ],
                            );
                          
                        );
                  );
                
              ,
            )));
  

第 4 步:

class EmployeeDetailsPage extends StatelessWidget 
  final Employee employeeData;
  const EmployeeDetailsPage(this.employeeData);

  @override
  Widget build(BuildContext context) 
    return Scaffold(
      appBar: AppBar(
        title: Text('Employee Details'),
      ),
      body: Column(
        children: [
          Padding(
            padding: const EdgeInsets.all(8.0),
            child: Center(child: Text(employeeData.employeeName, style: TextStyle(fontSize: 30))),
          ),
          Padding(
            padding: const EdgeInsets.all(8.0),
            child: Center(child: Text(employeeData.designation, style: TextStyle(fontSize: 20))),
          ),
          Text('Salary $employeeData.salary.toString()'),

        ],
      ),
    );
  

【讨论】:

嘿@BalasubramaniSundaram 不幸的是它没有用,你能看看我的答案吗?【参考方案2】:

&lt;blockquote class="imgur-embed-pub" lang="en" data-id="a/aqBaJ7N" data-context="false" &gt;&lt;a href="//imgur.com/a/aqBaJ7N"&gt;&lt;/a&gt;&lt;/blockquote&gt;&lt;script async src="//s.imgur.com/min/embed.js" charset="utf-8"&gt;&lt;/script&gt;

嘿!不幸的是,它不起作用,看看发生了什么。

我认为这是因为我作为参数发送的索引,它不理解值已被过滤:

onTap: ()=> 
                       //print(data.documentID),
                       _navegarParaPerfil(context, items[index]),
                       

void _navegarParaPerfil(BuildContext context, Paciente paciente) async
    await Navigator.push(context,
     MaterialPageRoute(builder: (context) => TelaPaciente(paciente)),
     );
  

理想情况下,它将通过 documentID 而不是此索引进行验证,但我无法更改它

【讨论】:

以上是关于颤动中的Firebase列表的主要内容,如果未能解决你的问题,请参考以下文章

颤动中的Firebase分页

使用refreshToken颤动firebase自动刷新用户会话

如何在颤动中将数据从复选框存储到 Firebase

如何将图像从颤动的资产上传到firebase存储?

颤动的firebase身份验证提供者未通知

使颤动通知(通过firebase)弹出到前台(并且不仅仅是状态栏中的图标)