Skip to content

VIEWs Flutter Widgets

Valdio Veliu edited this page Mar 31, 2020 · 4 revisions

Thew VIEWs main purpose is to preset the data in an acceptable way for the user and allow the user to interact with this data, (scroll through them, tap on items, etc).

For this purpose, the VIEWs on this app are split into 2 main categories:

  • component Widgets, representing the UI units of the app like buttons, cards, toggles, etc.
  • feature Widgets, representing the main screens of the app or what is called a "feature" in our case.

Component Widgets

Component Widget's only purpose is to display some kind of information to the user based on some predefined UI restrictions. Also, they can intercept user inputs or evets like taps. Pretty much they are dumb components that are not aware of the state of the app.

Feature Widgets

Feature Widgets, as previously mentioned, represent the main screens of the app, so the features of the app. They are connected through each other by the Flutter Navigator. There are several ways to handle navigation in Flutter, but I prefer to set up the app's navigation in a structured manner. More on it on the wiki navigation-between-screens) .

Furthermore, the purpose of Feature Widgets is again to present some information to the user and scale fold the layout that the "dummy widgets" are presented, so the same as a regular widget so far. But in extension to that these Widgets can be connected to various VIEW-MODELS from whom they get their data from and to whom they "request a data change",e.g. change the status of a toggle.

It is a preference of mine, and also the way it is implemented in this small demo that each Feature has its own VIEW-MODEL to whom it connects to. But this is not limited, you can connect a widget to any particular ViewModel that you like depending on what part of the dataset the widget wants to access. Remember, everything to the VIEW layer will be served through some kind of ViewModel so the VIEW has no knowledge on how the data is actually available. It just is!

The following example is how a Widget is actually connected to a ViewModel and how it gets the data it required.

class GalleryScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    // 1. Connect to the part of the global state that is managed from `GalleryViewModel`
    return StoreConnector<AppState, GalleryViewModel>(
      converter: (Store<AppState> store) => GalleryViewModel.create(store),
      onInitialBuild: (vm) {
        // 2. perform actions on initial build of the widget.
        vm.loadImagesList();
      },
      builder: (context, vm) {
        // 3. get data from the ViewModel
        List<ImageItem> images = vm.galleryImages;

        return Scaffold(
          backgroundColor: Colors.white,
          body: Container(
            /// ... CONTENT OF THE WIDGET.
          ),
        );
      },
    );
  }
}

Comments

There are three key points in the code snippet above:

  1. The Widget is connecting to the part of the redux store managed by the mentioned ViewModel and only data that is available through that ViewModel can be accessed further in the render tree. Or otherwise, we need to connect to other parts of the state further in the tree.
  2. The store connector allows the widget to perform some actions on onInitialBuild like for example make a network call to get new data.
  3. We can access the data in the state through the ViewModel. vm is an instance of the same ViewModel.

All the exposed data and the available function that this Widget can access must be defined in the ViewModel. More on this check the wiki ViewModel-structure.

Clone this wiki locally