Flutter: implementing a search feature for data from a StreamBuilder with ListView Flutter: implementing a search feature for data from a StreamBuilder with ListView dart dart

Flutter: implementing a search feature for data from a StreamBuilder with ListView


You can take the following approach.

  1. You receive the complete data in snapshot.
  2. Have a hierarchy of widgets like :StreamBuilder(ValueListenableBuilder( ListView.Builder))
  3. Create ValueNotifier and give it to ValueListenable builder.
  4. Use Search view to change value of ValueNotifier.
  5. When value of ValueNotifier will change your ListView.builder will rebuild and at that time if you are giving the filtered list according to query to the ListView.builder then it will work for you the way you want it.

I hope this helps, in case of any doubt please let me know.

EDITED

You won't need ValueNotifier instead You will need a StreamBuilder. So your final hierarchy of widgets would be:StreamBuilder( StreamBuilder>( ListView.Builder ))

I didn't have an environment like yours so I have mocked it and created an example. You can refer it and I hope it can give you some idea to solve your problem. Following is a working code which you can refer:

import 'dart:async';import 'package:flutter/material.dart';void main() => runApp(MaterialApp(      home: Scaffold(        appBar: AppBar(),        body: SearchWidget(),      ),    ));class SearchWidget extends StatelessWidget {  SearchWidget({Key key}) : super(key: key);  @override  Widget build(BuildContext context) {    return SingleChildScrollView(      child: Column(        children: <Widget>[          TextField(onChanged: _filter),          StreamBuilder<List<User>>( // StreamBuilder<QuerySnapshot> in your code.            initialData: _dataFromQuerySnapShot, // you won't need this. (dummy data).            // stream: Your querysnapshot stream.            builder:                (BuildContext context, AsyncSnapshot<List<User>> snapshot) {              return StreamBuilder<List<User>>(                key: ValueKey(snapshot.data),                initialData: snapshot.data,                stream: _stream,                builder:                    (BuildContext context, AsyncSnapshot<List<User>> snapshot) {                      print(snapshot.data);                  return ListView.builder(                    shrinkWrap: true,                    itemCount: snapshot.data.length,                    itemBuilder: (BuildContext context, int index) {                      return Text(snapshot.data[index].name);                    },                  );                },              );            },          )        ],      ),    );  }}StreamController<List<User>> _streamController = StreamController<List<User>>();Stream<List<User>> get _stream => _streamController.stream;_filter(String searchQuery) {  List<User> _filteredList = _dataFromQuerySnapShot      .where((User user) => user.name.toLowerCase().contains(searchQuery.toLowerCase()))      .toList();  _streamController.sink.add(_filteredList);}List<User> _dataFromQuerySnapShot = <User>[  // every user has same enviornment because you are applying  // such filter on your query snapshot.  // same is the reason why every one is approved user.  User('Zain Emery', 'some_enviornment', true),  User('Dev Franco', 'some_enviornment', true),  User('Emilia ONeill', 'some_enviornment', true),  User('Zohaib Dale', 'some_enviornment', true),  User('May Mcdougall', 'some_enviornment', true),  User('LaylaRose Mitchell', 'some_enviornment', true),  User('Beck Beasley', 'some_enviornment', true),  User('Sadiyah Walker', 'some_enviornment', true),  User('Mae Malone', 'some_enviornment', true),  User('Judy Mccoy', 'some_enviornment', true),];class User {  final String name;  final String environment;  final bool approved;  const User(this.name, this.environment, this.approved);  @override  String toString() {    return 'name: $name environment: $environment approved: $approved';  }}