【问题标题】:Flutter: How can Realtime database be searched in a streambuilder?Flutter:如何在流构建器中搜索实时数据库?
【发布时间】:2022-01-25 00:24:49
【问题描述】:

我正在尝试通过 TextField 在流构建器中搜索实时数据库,该 TextField 将采用 TextEditingController。

数据正在显示,但不幸的是,当我在 TextField 中输入时,它不会查询/搜索我在 TextField 中输入的任何内容,那么我该如何在这里执行 Query/Search 方法?

这是我的代码:

    import 'package:flutter/material.dart';
    import 'package:idevice_me/providers/project_provider.dart';
    import 'package:idevice_me/screens/user_detail_screen.dart';
    import 'package:provider/provider.dart';
    import 'package:firebase_database/firebase_database.dart';
    
    
    
    class HomeWidget extends StatelessWidget {
      const HomeWidget({ Key? key }) : super(key: key);
      @override
      Widget build(BuildContext context) {
        
      TextEditingController searchData = TextEditingController();
      var dbref = FirebaseDatabase.instance.ref();
      var searchIng = dbref.orderByChild('users').onChildAdded;
      
        return StreamBuilder(
          stream: (searchData.text.trim() == '') ? searchIng : dbref.child('users').onValue,
          builder: (ctx, AsyncSnapshot snapshot){
            if(snapshot.connectionState == ConnectionState.waiting){
                    return const Center(child: CircularProgressIndicator());
                  }
            if(snapshot.hasData){
              //----------------------------
              //USERID comes from here
              //----------------------------
             final userSnapshot = snapshot.data!.snapshot.children.toList();
              return Column(
                children: [
                 const SizedBox(height: 20,),
                  Padding(
                    padding: const EdgeInsets.only(right: 15.0, left: 15.0),
                    child: TextField(
                              decoration: InputDecoration(
                                labelText: 'Search',
                                labelStyle: TextStyle(fontSize: 14,color: Colors.grey.shade400,fontWeight: FontWeight.w600),
                                enabledBorder: OutlineInputBorder(
                                  borderRadius: BorderRadius.circular(30),
                                  borderSide: BorderSide(color: Colors.grey.shade300),
                                ),
                                focusedBorder: OutlineInputBorder(
                                  borderRadius: BorderRadius.circular(30),
                                  borderSide: const BorderSide(color: Colors.blue),
                                ),
                                floatingLabelBehavior: FloatingLabelBehavior.auto,
                              ),
                              key: const ValueKey('search'),
                                
                                keyboardType: TextInputType.text,
                                controller: searchData,
                           

 onChanged: (value){
                               searchData.text = value;
                            }
                            ),
                  ),
                         const SizedBox(height: 20,),
                  Expanded(
                    child: ListView.builder(
                      itemCount: userSnapshot.length,
                      itemBuilder: (BuildContext ctx, i)=> Column(
                        children: [
                          // ignore: sized_box_for_whitespace
                          GestureDetector(
                            onTap: (){
                              Navigator.of(context).pushNamed(
                                UserDetailScreen.routeName, 
    
                                //--------------------------------------
                                //USERID should be here through snapshot
                                //--------------------------------------
    
                                arguments: userSnapshot[i].key.toString(),
                                );
                            },
                            
                            child: Column(
                              children: [
                                ListTile( 
                                  leading: const Icon(Icons.person),
                                  title: Text(userSnapshot[i].child('username').value,),
                                  subtitle: Text(userSnapshot[i].child('email').value,),
                                  trailing: Text(userSnapshot[i].child('phone').value.toString()),
                                  onTap: (){
                                    Navigator.of(context).pushNamed(
                                      UserDetailScreen.routeName,
                                      arguments: userSnapshot[i].key.toString()
                                      );
                                  },
                                ),
                                const Divider(),
                              ],
                            ),
                          ),
                        ],
                      )
                      ),
                  ),
                ],
              );
            }
            return const Center(child: Text('There is something wrong!'),);
          },
          );
    
          
      }
    
     
        
      }

【问题讨论】:

  • 您可以在TextField上使用onChange属性,在文本字段发生任何变化时调用获取数据的方法。
  • 没用 :'(

标签: flutter firebase-realtime-database


【解决方案1】:

您在搜索和不搜索的情况下从 Firebase 监听不同的事件:

                                          // ?
var searchIng = dbref.orderByChild('users').onChildAdded;
  
return StreamBuilder(
  stream: (searchData.text.trim() == '') ? searchIng : dbref.child('users').onValue,
                                                                           // ?

这两个事件完全不同:

  • onChildAdded:为您读取的路径下的每个 child 节点触发,或者与您的查询匹配。
  • onValue:使用单个快照触发一次,该快照包含您读取的路径下的所有子节点,或者与您的查询匹配。

所以当你在这里使用onValue 时,你需要在你的代码中循环遍历子节点。但是,如果您使用 onChildAdded,Firebase SDK 已经为您完成了该循环,您的代码中不需要它。

由于您似乎希望在此处列出snapshot.data!.snapshot.children.toList(),因此我建议在这两种情况下都收听onValue

这至少应该让您搜索和非搜索案例都显示用户列表。


要使实际搜索正常工作,您需要使用查询:

dbref.child('users').orderByChild('username').equalTo('Abdallah').onValue

【讨论】:

  • 所以你的意思是这样做:TextEditingController searchData = TextEditingController(); var dbRef = FirebaseDatabase.instance.ref().child('users');查询搜索 = dbRef.orderByChild('users'); --> StreamBuilder( 流: (searchData.text.trim() == '') ? search.onValue : dbRef.onValue,
  • 我试图这样做,但不幸的是它没有工作它仍然返回('users')中的所有数据它没有返回我正在搜索的内容:'(
  • 您尚未搜索任何内容,因此这是意料之中的。我只是修复了您代码中的一些错误,而不是全部。 --- 我也添加了一个如何对我的答案进行简单查询的示例。
  • 谢谢你,你是我的 Flutter HERO 太棒了! dbref.child('users').orderByChild('username').equalTo('Abdallah').onValue,按预期工作,但现在唯一的事情是如果我们需要通过 TextField 获取数据怎么办!我试图从 equalTo(searchData.text.trim() --> (这是 TextEditingController) ) 获取数据,然后我去了 TextFiel (controller: searchData) 但它没有用:(,那是什么最佳实践!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-11-22
  • 1970-01-01
  • 1970-01-01
  • 2019-12-18
  • 2021-12-08
  • 2019-05-24
  • 2020-08-01
相关资源
最近更新 更多