Mastering Flutter Development: Building a Counter App with Stream and RxDart

Mastering Flutter Development: Building a Counter App with Stream and RxDart

Welcome to my latest project in Flutter! As a developer, I am always looking for new ways to master my skills and techniques, and what better way to do that than to create an app from scratch? In this post, I will take you through the development process of a simple counter app using Flutter.

While a counter app may seem trivial, it actually presents a great opportunity to learn and practice fundamental concepts in Flutter, such as working with widgets, managing state, and handling user input. It's also a great way to get familiar with the Flutter framework, especially for beginners just starting out.

Throughout this post, I will share my thought process, the challenges I faced, and the lessons I learned as I developed this app. By the end of it, you should have a solid understanding of how to build a simple app in Flutter and be ready to take on more complex projects. So, let's get started!

Steps

  • create your app with the flutter create command

      flutter create counter_app
    
  • create a counter_bloc class to contain the logic

    The counter_bloc class would have the integer variable counter initialized to zero and a counter controller is declared to be a behaviour type stream of initial seed zero, then we create a getter of type stream<int> counter to access the streamed counter value

    We then create a function that increases the counter value by one and updates the counter stream counter value

      //with bloc i have to seperate the vusiness ui from the logic
      //by creating a class that serves as a middleman between the ui
      //and logic
    
      import 'package:rxdart/rxdart.dart';
    
      class CounterBloc {
        int _counter = 0;
    
        final _controlcounter = BehaviorSubject<int>.seeded(0);
    
        Stream<int> get counter => _controlcounter.stream;
        //we create a getter counter that returns a stream  of typer int
        //of the counter
    
        void incrementCounter() {
          _counter++;
          _controlcounter.sink.add(_counter);
          // this function does two things
          //first it increases the value of the counter value by one
          //then it pushes the just pdated counter integer variable to
          // the control counter with the sink.add method
        }
    
        void dispose() {
          _controlcounter.close();
          //the function dispose closes the controlcounter when its no longer needed
        }
      }
    
  • create a counter screen class to contain the user interface

    The design for the user interface is basically a centre widget to display the counter value and a button to increase it on click.

    other peculiarities are accessing the increment function in the counter bloc class by importing the file.

    Then we create a variable _counterBloc to access the counterBloc class, then we use it to get the streamed counter value which the StreamBuilder widget that returns the Text widget then shows the counter value

      import 'package:flutter/material.dart';
      import 'counterbloc.dart';
    
      class CounterScreen extends StatefulWidget {
        const CounterScreen({super.key});
    
        @override
        State<CounterScreen> createState() => _CounterScreenState();
      }
    
      class _CounterScreenState extends State<CounterScreen> {
        final _counterBloc = CounterBloc();
    
        @override
        void dispose() {
          _counterBloc.dispose();
          super.dispose();
        }
    
        @override
        Widget build(BuildContext context) {
          return Scaffold(
            appBar: AppBar(title: const Text('CounterBloc App')),
            body: Center(
              child: StreamBuilder(
                stream: _counterBloc.counter,
                initialData: 0,
                builder: (context, snapshot) => Text(
                  'counter has been tapped' + snapshot.data.toString() + ' times',
                  style: const TextStyle(fontSize: 40),
                ),
              ),
            ),
            floatingActionButton: FloatingActionButton(
              onPressed: () {
                _counterBloc.incrementCounter();
              },
              child: const Icon(Icons.add),
            ),
          );
        }
      }
    

Challenges

while coding the app, I encountered some errors

First mistake

My wonderful self wanted to convert the whole class to string.

 Center(
        child: Text(
          _counterBloc.toString(),
          style: TextStyle(fontSize: 60),
        ),
      ),

Another mistake

Center(
        child: StreamBuilder(
          stream: _counterBloc.counter,
          initialData: 0,
          builder: (context, snapshot) => Text(
            snapshot.toString(),
            style: const TextStyle(fontSize: 40),
          ),
        ),
      ),

the mistake in simple words, the snapshot is of type AsyncSnapshot<int> and cant be converted to a type string with just the toString() method

Final Result

Center(
        child: StreamBuilder(
          stream: _counterBloc.counter,
          initialData: 0,
          builder: (context, snapshot) => Text(
            'counter has been tapped' + snapshot.data.toString() + ' times',
            style: const TextStyle(fontSize: 40),
          ),
        ),
      ),

Conclusion

In conclusion, building a counter app using Stream and RxDart was a great way to practice and improve my skills in Flutter development. By utilizing these powerful tools, I was able to create a simple but effective app that demonstrates the potential of Flutter as a mobile development platform.

Throughout the process, I encountered some challenges, such as handling errors and working with asynchronous code. However, these challenges allowed me to learn new techniques and approaches, which will undoubtedly come in handy in future projects.

Overall, I hope this post has been informative and helpful to anyone looking to improve their Flutter development skills.