First, state management problems

There is a controversial part of Flutter – how should it be managed

At the beginning, I insisted on the idea of mobile terminal, using MVC or MVP, etc. Some students supported the front end idea, using Redux or RxDart, etc. Some said That Google recommended BLoC, and there was also an article I translated: Let me help you understand and choose a Flutter state management scheme, using a mixture of Redux and BLoC.

  • State and refresh are separated in MVC and MPV
  • Redux is a bit bloated with all the states in one place, and there are also unnecessary UI refreshes, which should be avoided in apps
  • BLoC uses tools such as Stream or RxDart to isolate the data (status) and then automatically update the data user when the status is updated

I was wondering if I could do it the way I developed it on iOS, but it didn’t work. The reason for this is that Flutter renders completely differently from mobile. It uses the React mentality.

Mobile UI controls can change their appearance by modifying their properties, but the styles of flutter and RN are basically rerendered. To update the content, change the state, and then update the UI with setState().

So updates to the UI in Flutter are inherently fragmented, just like React, and therefore require the encapsulation of an observer (or something similar) design pattern to reduce the complexity of UI updates, reduce coupling or excessive state declarations.

B

Having said that, BLoC is worth a try. It can solve the problem of mixing state and UI, and is not as heavy as Redux, so it is suitable for data synchronization in simple business scenarios.

BLoC is a design pattern, officials gave no encapsulate code, code to the same search on the net (don’t know if Google to best practice), but their common characteristic is that the initial value assignment problems, the initial value of the UI without BLoC data section of the initial value, just happened to the two values are equal, So when you have to change the initial value, you have to change a lot of things, which is obviously not acceptable. (The reasons won’t be repeated here.)

As I just said, the implementation of BLoC uses Stream or RxDart. I prefer to use Stream because it is a built-in library. I did not evaluate the RxDart function, but it is obviously too heavy for simple business scenarios.

Details about the realization of the BLoC, here recommend you to look at our article: Flutter | state management to explore – BLoC (3), I am here is unknown dwell on

BLoC has the following structure:

I don’t know if this should be classified as the watcher model or the producer-consumer model, but here it is:

  • The BLoC data module holds a StreamController to manage the stream

  • Where the UI needs to display data, use StreamBuilder to listen for stream changes

  • When the data in the Stream changes, the child UI is automatically refreshed.

  • When data needs to be updated, such as when a button is clicked, the BLoC data module is manipulated to update the data in it via its StreamController, and the UI is refreshed automatically.

BLoC packaging

Unconsciously, the purpose of this article is to encapsulate BLoC so that the Stream class is no longer exposed to business code.

The Pub warehouse:

Realank_flutter_bloc Domestic mirror image

The package is divided into three parts:

RLKBaseBLoC: Data class, which stores any type of data data (paradigm) and a changeData method that changes the data. Data is used by data consumers, and data workers changeData using changeData.

You can inherit it to define your own data content and add methods for updating the data. Creating a data instance is as simple as passing the initial data to be stored into the constructor:

Class CountBLoC extends RLKBaseBLoC<int> {//RLKBaseBLoC subclass extends RLKBaseBLoC<int> {// CountBLoC(int data) : super(data);increment() { changeData(data + 1); } } CountBLoC(0); / / RLKBaseBLoC instanceCopy the code

RLKBloCProvider: This is a Widget that saves the RLKBaseBLoC instance. In example, it covers the whole MaterialApp. Its function is to provide data sources where data is needed, as long as it is the common root node of all wideGT using RLKBaseBLoC data. If your RLKBaseBLoC data is only shown in A lot of places on page A, then the RLKBloCProvider only needs to wrap around page A.

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    returnRLKBloCProvider(// Wraps the whole APP because the data is used by two pages bloc: CountBLoC(0),// saves the RLKBaseBLoC instance Child: MaterialApp(theme: ThemeData.light(), home: TopPage(), ), ); }}Copy the code

RLKBLoCBuilder: When you need to use RLKBaseBLoC data, wrap the RLKBLoCBuilder around the widget. This widget provides you with an instance of RLKBaseBLoC data. For example, The RLKBloCProvider that saved the RLKBaseBLoC instance was placed in main.dart, but when I wanted to use the RLKBaseBLoC instance in TopPage, I couldn’t get it directly. Through RLKBLoCBuilder, You can get the RLKBaseBLoC instance as a parameter in the builder method.

Center(child: RLKBLoCBuilder(builder: (BuildContext context, int data, RLKBaseBLoC bloc) {
        return Text(
          'You hit me: $data times',); }))Copy the code

Finally, when you want to update the data, you can also get the RLKBaseBLoC instance through RLKBLoCBuilder and then operate on the data

class _STFState extends State<UnderPage> {
  @override
  Widget build(BuildContext context) {
    return RLKBLoCBuilder(builder: (BuildContext context, int data, RLKBaseBLoC bloc) {
      CountBLoC bloc2 = bloc as CountBLoC;
      return Scaffold(
        appBar: AppBar(
          title: Text('Under Page'),
        ),
        body: Center(
            child: Text(
          "You hit me: $data times",
          style: Theme.of(context).textTheme.display1,
        )),
        floatingActionButton: FloatingActionButton(
          onPressed: () {
            setState(() {}); bloc2.increment(); // Change data}, child: Icon(icon.add),); }); }}Copy the code

Four,

When you want more flexibility in managing state and UI, using this package allows you to get away from complex concepts like Redux, RxDart, Stream, etc., with just one data class and two containers, Widegt, good separation of data and UI, and less intrusive library code. I hope it helps.