Moving to Flutter ?
When I started Flutter I was working on a shopping app with Android and iOS native. I start with a course “Learn Flutter & Dart to Build iOS & Android Apps” on Udemy, it’s a great course I watched the first 5 modules and said it’s a very easy language and framework, and start to install it to vscode, add android studio and I found a plugin to android studio “Flutter App Template Generator” it helped me get to structure my project based on redux.
Project structure
The project based on Redux. It like MVI (Model – View – Intent) structure.
The app has the following packages:
- data: contains all the data accessing and manipulating components.
- features: contains screens and views.
- redux: contains store, states, actions, middlewares and reducers.
- trans: manage translation in app.
- utils: contains utils classes.
Data
Data package is responsible for handling the data part of the application.
- Models
- Remote repositories
- Network manager
Models
Pojo classes contain data, have 2 methods fromJson and toJson
fromJson
is named constructor take argument of Map<String, dynamic> to parse json from remote repository response.
dynamic islike Any in kotlin or swift
You can think of named constructor as static function that create object from class (factory pattern)
toJson
is a method used when post the object to remote
Remote repositories
It manages the network API calls and API data handling using Dio.
Dio
Dio is a powerful Http client for Dart, which supports Interceptors, Global configuration, FormData, Request Cancellation, File downloading, Timeout etc.
Dio is like OkHttp & Retrofit in android or Alamofire in ios
NetworkCommon is singleton class to manage network API calls.
- Global configuration like base url and timeout.
- Interceptors for request to put accept-language and content-type and for response to log it or handle response globally.
use NetworkCommon in repositories
Alice
I used alice with dio to inspecting HTTP requests. Alice is an HTTP Inspector tool for Flutter which helps debugging http requests. It catches and stores http requests and responses, which can be viewed via simple UI.
Alice is like Chuck in android
and add this to dio in NetworkCommondio.interceptors.add(alice.getDioInterceptor());
Features
It is responsible for laying out the views with specific data on the screen.
ViewModel
Each screen has view and viewmodel that created from store using redux & flutter_redux
- Get store by StoreConnector
According to flutter_rudex StoreConnector is
A descendant Widget that gets the Store from the nearest
StoreProvider
ancestor, converts theStore
into aViewModel
with the givenconverter
function, and passes theViewModel
to abuilder
function. Any time the Store emits a change event, the Widget will automatically be rebuilt. No need to manage subscriptions!
More details about using Redux in the app will be discussed in the next section.
2. Create viewmodel by static function take store and return viewmodel (factory)
3. Pass viewmodel to view
How to use Redux in your app
Redux is an Application State Management framework. In other words, its main objective is to manage a State.
A nice introduction for Redux https://blog.novoda.com/introduction-to-redux-in-flutter/
Redux one of 3 most commonly used frameworks (BLoC – ScopedModel – Redux), the course teach ScopedModel.
I used redux
- Redux allows to centralize the management of a State thanks to the fact that Reducers are the only one(s) that can perform the transition from one state to another. This makes the state transition perfectly predictable and thoroughly testable.
- The ease to insert middlewares in the flow is also an asset. If, for example, you need to constantly validate the connectivity with the server or trace the activities, this is a perfect placeholder for such routines.
- It forces the developer to structure the application in terms of “Event -> Action -> Model -> ViewModel -> View”.
When to be used ?
- I could recommend Redux when you need to deal with a global application state, such as, e.g., user authentication, shopping basket, preferences (language, currency)…
- I would not recommend Redux when you need to handle multiple instances of something, each of them having its own State
To create store you need for three component
- App reducers
- App state
- Middleware (optional)
Actions
Actions are the only types of input accepted by the Store access point. Actions, combined with the current State are used by the Middleware(s) and Reducer to process some function, which could lead to amending the State.
Actions only describe what happened
App reducers
A Reducer is normally a synchronous function which does some processing based on the combination Action — State. The outcome of the processing might lead to a new State.
The Reducer is the only one allowed to change the State.
Middleware
A Middleware is a function commonly aimed at running asynchronously (but not necessarily), based on an Action. A Middleware simply uses a State (or an Action as a trigger) but does not change the State.
It is important to note that, according to Redux recommendations and good practices, there is only one single Store per application. To split the data handling logic, it is advised to use ‘reducer composition’ instead of many stores.
How does it work?
- When something happens at the UI level (but not limited to the UI, in fact), an Action is created and sent to the Store (via store.dispatch(action));
like in NotificationsViewModel
store.dispatch(GetNotificationsAction(isRefresh: isRefresh));
- If one or several Middlewares are configured, they are invoked in sequence, passing them the Action and a reference to the Store (so, also the State, indirectly);
- Middlewares could themselves send an Action to the Store during their processing
next(SyncNotificationsAction(page: page, notifications: list));
- Then the Action and the current State are also sent to the Reducer
- The Reducer is the only one that will potentially change the State
- When the State is changed, the Store notifies all registered listeners to inform them.
- The UI (but not limited to the UI) can then take appropriate actions linked to change of State.
Debugging redux
I wanted to see my store to ensure every thing is working, So i used flutter_redux_dev_tools with chrome extension Redux DevTools
Redux DevTools like Reactotron in reactnative
make sure to install and run
npm install -g remotedev-server
remotedev --port 8000
Last tip make sure to use function toJson to show store
Data in store showing in remote debug
Bonus
Flutter icon
I used http://fluttericon.com/ to add icons to app. FlutterIcon is a web-based generator of Flutter icon font elements. Customized icon fonts can be produced from not only Material Design Icons, but several popular open source webfonts as well, or by uploading your own svg art.
Conclusions
I think it is an exciting experiment to try. Flutter and Dart have a very cool learning curve and an elegant syntax. Moving from Android or iOS to Flutter is not easy of course, But it deserves a risk. Redux is life saver when things get complicated. And it’s a good choice for many medium to large applications.
Lee Luong – Co Founder & CEO