1

Flutter Dart

I am a beginner in flutter and i am trying to add controller to streamBuilderWidget so i can dispose it but i have no idea where should i put the controller.. i tried this

the stream below as a widget not function

StreamController<QuerySnapshot> controller;
        void dispose() {
            super.dispose();
            controller.close();
          }
        
          void initState() {
            super.initState();
            controller = StreamController<QuerySnapshot>();
          }
        
         StreamBuilder<QuerySnapshot>(
    stream: FirebaseFirestore.instance.collection("users").doc(widget.documentUid).snapshots(),
     builder: (BuildContext context, AsyncSnapshot<QuerySnapshot> snapshot) {
         if (!snapshot.hasData) {
              return Center(
              child: circulearProgress(),
            );
}

in this code it never disposed or closed the stream:(

Anyone who edits my code in the right way will be very grateful to him , thanks friends

Jack
  • 161
  • 1
  • 16

3 Answers3

4

StreamController is like a pipeline. In your case, that pipeline went from water supplier to your house, there is no need to worried about what goes in there. But if you want to set up a pipeline from your washing machine to the draining hole, that is where you need to use StreamController. Example:

class HomeScreen extends StatefulWidget {

  @override
  _HomeScreenState createState() => _HomeScreenState();
}

class _HomeScreenState extends State<HomeScreen> {
  final NumberController controller = NumberController();

  @override
  void dispose() {
    controller.dispose();
  }
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: SafeArea(
        child: SingleChildScrollView(
          child: Column(
            children: [
              InputWidget(controller: controller,),
              OutputWidget(controller: controller,)
            ],
          ),
        ),
      ),
    );
  }
}

class NumberController {
  //This is the pipeline of "number"
  final StreamController<int> controller = StreamController<int>.broadcast();

  //This is where your "number" go in
  Sink<int> get inputNumber => controller.sink;

  //This is where your "number" go out
  Stream<int> get outputNumber => controller.stream;

  //Dispose
  void dispose() {
    controller.close();
  }
}

class InputWidget extends StatelessWidget {
  final NumberController controller;

  const InputWidget({Key key, this.controller}) : super(key: key);
  @override
  Widget build(BuildContext context) {
    return InkWell(
        onTap: () {
            controller.inputNumber.add(Random().nextInt(10));
        },
    child: Text(
      'Random Number'
    ),);
  }
}

class OutputWidget extends StatelessWidget {
  final NumberController controller;

  const OutputWidget({Key key, this.controller}) : super(key: key);
  @override
  Widget build(BuildContext context) {
    return StreamBuilder<int>(
      stream: controller.outputNumber,
      builder: (context, snapshot) {
        return Text(snapshot.hasData ? snapshot.data.toString() : 'No data');
      },
    );
  }
}
Phuoc
  • 966
  • 3
  • 7
  • 20
  • thanks a lot for awesome example , i have this handleDelete(){ FirebaseFirestore.instance.collection("handleCountM").doc(currentUser.uid + widget.documentUid).collection("handleCountM2").limit(1).snapshots().listen((value) { value.docs.forEach((element) { element.reference.delete(); }); }); } how could i close it when i press on the back button – Jack Jul 23 '21 at 09:28
0

You don't have to use StreamController. StreamBuilder you are using closes the stream internally.

Rahul
  • 4,699
  • 5
  • 26
  • 38
  • thanks for this information but i am trying to close this function when i press on the back bottom FirebaseFirestore.instance.collection("handleCountM").doc(currentUser.uid + widget.documentUid).collection("handleCountM2").limit(1).snapshots().listen((value) { value.docs.forEach((element) { element.reference.delete(); }); }); } how could i close it when i press on the back button – Jack Jul 23 '21 at 09:29
0

From your comments, you seem to want to close the listener in the method below:

void handleDelete() {
FirebaseFirestore.instance.collection("handleCountM").doc(currentUser.uid + widget.documentUid).collection("handleCountM2").limit(1).snapshots()
  .listen((value) { 
     value.docs.forEach((element) { 
       element.reference.delete(); 
     }); 
  }); 
}

You can do that by getting a reference to the stream subscription and calling .cancel on the subscription.

Calling .listen on a stream returns a stream subscription object like this:

StreamSubscription handleDeleteStreamSubscription =  FirebaseFirestore.instance.collection("handleCountM").doc(currentUser.uid + widget.documentUid).collection("handleCountM2").limit(1).snapshots()
  .listen((value) { 
     value.docs.forEach((element) { 
       element.reference.delete(); 
     }); 
  });

Cancelling the subscription is done like this:

handleDeleteStreamSubscription.cancel();
Victor Eronmosele
  • 7,040
  • 2
  • 10
  • 33