Flutter Control is complex library to maintain App and State management. Library merges multiple functionality under one hood. This approach helps to tidily bound separated logic into complex solution.

Overview

Structure

Structure


Flutter Control is complex library to maintain App and State management.
Library merges multiple functionality under one hood. This approach helps to tidily bound separated logic into complex solution.

import 'package:flutter_control/core.dart';
  • App State Management - Managing application state, localization, theme and other global App changes.
  • Widget State Management - UI / Logic separation. Controlling State and UI updates.
  • Dependency Injection - Factory, Singleton, Lazy initialization and Service Locator.
  • Navigation and Routing - Routes, transitions and passing arguments to other pages and Models.
  • Localization - Json based localization with basic formatting.
  • Event System - Global event/data stream to easily notify app events.

Flutter Control Core

  • Control Main static class. Initializes ControlFactory and provides easy access to most of core [Control] objects like BaseLocalization, RouteStore, ControlBroadcast, etc..
  • ControlFactory Initializes and can store Controls, Models and other Objects. Works as Service Locator and Storage.
    Factory has own Storage. Objects in this storage are accessible via custom key or Type. Best practice is to use Type as a key.
    Factory is one and only Singleton in this Library.
    Core objects of Flutter Control are stored in Factory's Storage by default (Control.initControl) and are accessible by their Type or via Providers.

Structure

    Control.initControl(
      localization: LocalizationConfig(
        defaultLocale: 'en',
        locales: LocalizationAsset.map(locales: ['en_US', 'es_ES']),
      ),
      entries: {
        CounterListControl: CounterListControl(),
      },
      initializers: {
        CounterModel: (_) => CounterModel(),
        CounterDetailControl: (args) => CounterDetailControl(model: Parse.getArg<CounterModel>(args)),
      },
      routes: [
        ControlRoute.build<DetailPage>(builder: (_) => DetailPage()),
      ],
      initAsync: () async {
        loadPreAppConfig();
      },
    );
  • ControlRoot Wraps basic app flow and initializes [Control]. It's just shortcut to start with Flutter Control. Via ControlScope is possible to maintain State of this root widget and control whole app state (localization, theme, etc.).
    Additionally offers App State management - home screen, localization and theme changes.
    ControlRoot(
      localization: LocalizationConfig(locales: [...]),
      theme: ThemeConfig<MyThemne>(
        builder: (context) => MyTheme(context),
        themes: {...},
      ),
      entries: {...},
      initializers: {...},
      routes: [...],
      states: [
        AppState.init.build(builder: (_) => LoadingPage()),
        AppState.main.build(
          builder: (_) => DashboardPage(),
          transition: TransitionToDashboard(),
        ),
      ],
      app: (setup, home) => MaterialApp(
        key: setup.key,
        title: setup.title('app_name', 'Example App'),
        theme: setup.theme,
        home: home,
        locale: setup.locale,
        supportedLocales: setup.supportedLocales,
        localizationsDelegates: [
          ...
        ],        
      ),
    );

  • ControlWidget is base abstract class (StatefulWidget) to maintain larger UI parts of App (Pages or complex Widgets). Widget is created with default ControlState to correctly reflect lifecycle of Widget to Models. So there is no need to create custom [State].
    Widget will init all containing Models and pass arguments to them.
    ControlWidget is immutable so all logic parts (even UI logic and animations) must be controlled from outside. This helps truly separate all code from pure UI (also helps to reuse this code).

  • SingleControlWidget is focused to single ControlModel. But still can handle multiple Controls.

  • ControllableWidget - Subscribes to one or more Observable - [ObservableComponent], [ActionControl], [FieldControl], [Stream], [Future], [Notifier]
    Whenever state of [ControlObservable] is changed, this Widget is rebuild.

    These Widgets comes with few mixin classes:

    • RouteControl to abstract navigation and easily pass arguments to Routes and init other Pages.
    • TickerControl and SingleTickerControl to create [State] with Ticker and provide access to vsync.
    • LocalizationProvider, ThemeProvider, OnLayout, ControlsComponent and more..
  • ControlModel is base class to maintain Business Logic parts.
    BaseControl is extended version of [ControlModel] with more functionality. Mainly used for Pages or complex Widgets and also to separate robust Logic parts.
    BaseModel is extended but lightweight version of [ControlModel]. Mainly used to control smaller Widgets like Items in dynamic List or to separate/reuse Logic parts.
    This Controls comes with few mixin classes to extend base functionality:

    • ObservableComponent to control State and notify Widget about changes.
    • TickerComponent passes Ticker to Model and enables to control animations outside of Widget.

Structure

  • ControlObservable and ControlSubscription are core underlying observable system and abstract base for other concrete robust implementations - mainly [ActionControl] and [FieldControl].
    With ControlBuilder and ControlBuilderGroup on the Widget side. These universal builder widgets can handle all possible types of Notifiers.

  • ActionControl is one type of Observable used in this Library. It's quite lightweight and is used to notify Widgets and to provide events about value changes.
    Has two variants - Single (just one listener), Broadcast (multiple listeners).
    On the Widget side is ControlBuilder to dynamically build Widgets. It's also possible to use ControlBuilderGroup to group values of multiple Observables.
    Upon dismiss of [ActionControl], every ControlSubscription is closed.

    final counter = ActionControl.broadcast<int>(0);

    ActionBuilder<int>(
      control: counter,
      builder: (context, value) => Text(value.toString()),
    );
  • FieldControl is more robust Observable solution around Stream and StreamController. Primarily is used to notify Widgets and to provide events about value changes.
    Can listen Stream, Future or subscribe to another [FieldControl] with possibility to filter and convert values.
    [FieldControl] comes with pre-build primitive variants as StringControl, DoubleControl, etc., where is possible to use validation, regex or value clamping. And also ListControl to work with Iterables.
    On the Widget side is FieldBuilder to dynamically build Widgets. Also ControlBuilderGroup for use with multiple Observables. It's also possible to use standard StreamBuilder.
    FieldSink or FieldSinkConverter provides Sink of [FieldControl].
    Upon dismiss of [FieldControl], every FieldSubscription is closed.
    final counter = FieldControl<int>(0);

    FieldBuilder<int>(
      control: counter,
      builder: (context, value) => Text(value.toString()),
    );

Check Counter Example and TODO List Example at Git repository.


Structure below shows how data and events flows between UI and Controls. ControlWidget can use multiple ControlModels with multiple Models, Streams and Observables.. Structure


Localization

  • BaseLocalization Json based localization, that supports simple strings, plurals and dynamic structures.
    Easy access via LocalizationProvider mixin. Localization object is stored in [ControlFactory], so is accessible without context and can be used even in Models, Entities, etc. via Control.localization()
    Localization is initialized and loaded in Control by default.
    And by default ControlWidget uses this localization via mixin.
    Control.initControl(
      localization: LocalizationConfig(
        defaultLocale: 'en',
        locales: LocalizationAsset.map(locales: ['en_US', 'es_ES']),
      ),
    );
    ControlRoot(
      localization: LocalizationConfig(
        locales: {
          'en': 'assets/localization/en.json',
          'es': 'assets/localization/es.json',
        },
      ),
    );

Check Localization Example and Localization Delegate Example at Git repository.

Global Event System

  • ControlBroadcast Event stream across whole App. Default broadcaster is part of ControlFactory and is stored there.
    Every subscription is bound to it's key and Type so notification to Listeners arrives only for expected data.
    With BroadcastProvider is possible to subscribe to any stream and send data or events from one end of App to the another, even to Widgets and their States. Also custom broadcaster can be created to separate events from global/default stream.

Structure

  BroadcastProvider.subscribe<int>('on_count_changed', (value) => updateCount(value));
  BraodcastProvider.broadcast('on_count_changed', 10);

Navigation and Routing

  • ControlRoute Specifies Route with Transition and [WidgetBuilder] settings for RouteHandler. Handler then solves navigation and passes args to Widgets and Models.
    Use RouteControl mixin to enable this navigation with [ControlWidget] and RouteControlProvider mixin with [ControlModel]. Routes can be stored in RouteStore and Route builder is accessible statically via ControlRoute.of.
    Control.initControl(
      routes: [
        ControlRoute.build<DetailPage>(builder: (_) => DetailPage()),
        ControlRoute.build(key: 'detail_super', builder: (_) => DetailPage()).path('super').viaTransition(_transitionBuilder),
      ],
    );

    class ListPage extends ControlWidget with RouteControl {
      Widget build(BuildContext context){
        ...
        routeOf<DetailPage>().openRoute();
        routeOf<DetailPage>().viaTransition(_transitionBuilder).openRoute();
        routeOf(key: 'detail_super').openRoute();
      };
    }

Check Navigation Example and Navigation Stack Example at Git repository.


Other classes

  • ControlTheme and ThemeProvider Wraps [ThemeData], [MediaQuery] and asset path helper.

  • InputField Wrapper of [TextField] to provide more functionality and control via InputControl.

  • DisposeHandler - mixin for any class, helps with object disposing.

  • PrefsProvider - mixin for any class, helps to store user preferences - based on shared_preferences.

  • Parse Helps to parse json primitives and Iterables. Also helps to look up Lists and Maps for objects.

  • FutureBlock Retriggerable delay.

  • DelayBlock Delay to wrap a block of code to prevent 'super fast' completion and UI jiggles.

  • WidgetInitializer Helps to initialize Widgets with init data.

  • UnitId Unique Id generator based on Time, Index or just Random.

  • and more..


Check set of Flutter Control Examples at Git repository for more complex solutions and how to use this library.

You might also like...

Generic validator - A generic validator with business logic separation in mind

This package provides APIs to facilitate separating validation and business rule

May 19, 2022

MV* Architectures - Responsible for the business logic of the application.

MV* Architectures - Responsible for the business logic of the application.

MV* Architectures MVC Model Responsible for the business logic of the application. Persisting application state: communication with the database. Data

Mar 15, 2022

State Persistence - Persist state across app launches. By default this library store state as a local JSON file called `data.json` in the applications data directory. Maintainer: @slightfoot

State Persistence Persist state across app launches. By default this library store state as a local JSON file called data.json in the applications dat

Sep 28, 2022

A library that helps you have multiple snackbars as a column

multi_snackbar A set of commands that helps you display more than one snackbar at the same time. Getting Started Make a list of widgets: var widgets =

Dec 23, 2021

An extension to the bloc state management library which lets you create State Machine using a declarative API

An extension to the bloc state management library which lets you create State Machine using a declarative API

Aug 15, 2022

Flutter App Templete is a project that introduces an approach to architecture and project structure for developing Flutter apps.

Flutter App Template "Flutter App Template" is a project that introduces an approach to architecture and project structure for developing Flutter apps

Sep 13, 2022

EasiestSqlFlutter - The Easiest and the Laziest approach to Flutter SQL Database.

EasiestSqlFlutter - The Easiest and the Laziest approach to Flutter SQL Database.

The Easiest and the Laziest approach to Flutter SQL Database for Flutter. • How to use • Contribution • License • Support • Share Sharing with your fr

Jul 27, 2022

An all-in-one Fllutter package for state management, reactive objects, animations, effects, timed widgets etc.

An all-in-one Fllutter package for state management, reactive objects, animations, effects, timed widgets etc.

Frideos An all-in-one package for state management, streams and BLoC pattern, animations and timed widgets, effects. Contents 1. State management Gett

Sep 22, 2022

Yet another localization approach in Flutter

Yet another localization approach in Flutter

Flutter Global Summit Vol.2 schedule Source code of the mobile application that displays the schedule of the Flutter Global Summit Vol.2 conference th

Mar 24, 2022
Comments
  • Architecture

    Architecture

    This is very well done.

    I am using hive to back my domain model. It's really great I find.

    Would you consider this a good persistence lib for your framework ? Or do you want to keep it open so anyone can inject what they want ? You basically doing a IOC pattern from what I can see

    discussion 
    opened by gedw99 3
  • Hey there! Superb Package!

    Hey there! Superb Package!

    Hey there RomanBase,

    First of all, thank you so much for your dedication and time. This package looks amazing! Please do not take this as a request or anything like that, I'm legit curious if you're planning on releasing a written tutorial about your amazing work?

    Thanks!

    opened by joanofdart 1
  • Widget types

    Widget types

    Event architecture.

    This is a great project.

    Hook up Server side svents. There is a dart like for it. Typically the server sends a create, update or delete to I dictate what change occurred on a data row. The ID is normally in the message just like a typical database row

    opened by ghost 1
  • Allow pages to stop from navigating away, e.g. if there are unsaved state changes

    Allow pages to stop from navigating away, e.g. if there are unsaved state changes

    Hello, I am going to start a web project with Flutter, for another project use the Fluro library, however, I could not solve the following problem: If a user is on a page that contains a form and is making modifications is said form, I would like that if he tries to exit without having saved the modifications (either by putting another url, with the browser's backbutton, ...) it would show him an alertdialog giving him the possibility of canceling the navigation to the new url or, on the contrary, of canceling the modifications and staying on the same page where he is. The question is, can I do this with flutter_control? flutter_control has any mechanism by which this functionality can be achieved? Please, if this functionality is possible with flutter_control could you give me some indications. Thank you so much for all the help. Regards, Jose

    opened by Josua2012 2
Owner
Roman Hornak
Flutter is way to go.
Roman Hornak
GetX - one of the most popular state management solution in flutter

GteX Tutorial - Udemy GetX is one of the most popular state management solution in flutter. In addition to state management, GetX provides easy way to

Md. Siam 3 May 18, 2022
A flutter demo app to practice ListView.separated

ListView 2 A flutter demo app to practice ListView.separated Developer Alexander Sosa

Alexander Sosa 0 Jan 3, 2022
Picture upload widget for Flutter which helps selecting and uploading one or multiple images to firebase storage.

Flutter Firebase Picture Uploader This library offers a Picture Upload widget which can be used to upload one or multiple images to your Firebase Stor

Christoph Rothermel 11 Aug 16, 2022
App to control your health activities like calorie, water, medicine consumption, sleeping and weight control.

Handy Configuration for yourself This project contains google-services.json file of my own. You can connect your own firebase project using the follow

KanZa Studio 98 Sep 23, 2022
Flutter remote control - The main use of LongPressDraggable and DragTarget to achieve the universal remote control interaction effect.

Flutter remote control - The main use of LongPressDraggable and DragTarget to achieve the universal remote control interaction effect.

唯鹿 161 Sep 14, 2022
⚡FQuery is a powerful async state management solution for flutter. It caches, updates and fully manages asynchronous data in your flutter apps.

⚡ FQuery is a powerful async state management solution for flutter. It caches, updates and fully manages asynchronous data in your flutter apps. It ca

Piyush 7 Sep 28, 2022
A simple state management solution that combine the power of inherited widget and rxdart

Inherited RxDart is a state management library that combine the power of InheritedWidget and RxDart, a simple and elegant state management solution for apps of any scale

Nguyễn Ngọc Phước 12 Sep 21, 2022
Cubit is a lightweight state management solution

Cubit is a lightweight state management solution. It is a subset of the bloc package that does not rely on events and instead uses methods to emit new states.

Felix Angelov 580 Sep 8, 2022
This repo is an example of clean architecture using the GetX state-management solution.

GetX Clean Architecture A Flutter Clean Architecture Using GetX. This repo is forked from: https://github.com/phamdinhduc795397/flutter-getx-clean-arc

Md. Siam 73 Sep 24, 2022
Learn how to build a multi-step form flow and how to use bloc to effectively isolate the presentation layer from the business logic layer.

Multi-page Form Flow Learn how to build a multi-step form flow and how to use bloc to effectively isolate the presentation layer from the business log

Sandip Pramanik 9 Sep 21, 2022