preface
Fish-redux is an official framework for Flutter state management. There are many commonly used state management frameworks, ranging from those officially recommended by Google to those written by individual developers. This article focuses on Fish_redux.
Common Flutter state management schemes:
Starting at zero, you know fish-Redux, for example
There are many ways to do this,
- Call setText(“${count+1}”)
- SetState (){“${count+1}”}
The native implementation of Flutter has no performance problems. OnDraw () is triggered when a setText is called. However, the implementation of Flutter calls setState causes the entire root layout to be rebuilt. How do you control the coarse-grained layout so that only the digital control layout that needs to change is rebuilt?
Fish-redux implementation
1. Build a Flutter project, Flutter2.0 is not supported because fish-Redux does not support Flutter2.0, now demo with version 1.22.6, add dependencies in pubspec.yaml,
Dependencies: flutter: SDK: flutter fish_redux: 0.3.7Copy the code
2. Download the FishReduxTemplate plugin
3. Create a folder called count, right-click it, and select FishReduxTemplate to generate the Page template code
4. Encode main.dart to create a page entry
import 'package:fish_redux/fish_redux.dart';
import 'package:flutter/material.dart';
import 'count/page.dart';
void main() {
runApp(MyApp());
}
///Routing management
class RouteConfig {
static const String countPage = 'page/count';
static final AbstractRoutes routes = PageRoutes(
pages: {
///Map your route name to the page, for example: RouteConfig. HomePage: homePage (),
RouteConfig.countPage: CountPage(),
},
);
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'FishReduxDemo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: RouteConfig.routes.buildPage(RouteConfig.countPage, null), // as the default page
onGenerateRoute: (RouteSettings settings) {
// Material page toggle style
return MaterialPageRoute<Object>(builder: (BuildContext context) {
returnRouteConfig.routes.buildPage(settings.name, settings.arguments); }); }); }}Copy the code
- Code Page. Dart
import 'package:fish_redux/fish_redux.dart';
import 'effect.dart';
import 'reducer.dart';
import 'state.dart';
import 'view.dart';
/// With the creation of the page, the Fish Redux framework creates Effect by default and the Reducer object manages the whole page
class CountPage extends Page<CountState.Map<String.dynamic>> {
CountPage()
: super(
initState: initState, // Create a default state object
effect: buildEffect(), // Create an Effect object
reducer: buildReducer(), Create a Reducer object
view: buildView, // Create the page layout, here is the actual page to display
dependencies: Dependencies<CountState>(
adapter: null,
slots: <String, Dependent<CountState>>{},
),
middleware: <Middleware<CountState>>[],
);
}
Copy the code
- Code view.dart
import 'package:fimber/fimber_base.dart';
import 'package:fish_redux/fish_redux.dart';
import 'package:flutter/material.dart';
import 'action.dart';
import 'state.dart';
/// The View layout shown on the home page
Widget buildView(CountState state, Dispatch dispatch, ViewService viewService) {
return _bodyWidget(state, dispatch);
}
Widget _bodyWidget(CountState state, Dispatch dispatch) {
return Scaffold(
appBar: AppBar(
title: Text("FishReduxDemo"),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(state.count.toString(), style: TextStyle(fontSize: 40, color: Colors.red)),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: () {
dispatch(CountActionCreator.increaseCount()); // 1. Click the event trigger
},
child: Icon(Icons.add),
),
);
}
Copy the code
- Code effect.dart
import 'package:fimber/fimber_base.dart';
import 'package:fish_redux/fish_redux.dart';
import 'action.dart';
import 'state.dart';
Effect<CountState> buildEffect() {
// Combine effect
return combineEffects(<Object, Effect<CountState>>{
CountAction.increase: _onIncreaseCount,
});
}
///On the way
void _onIncreaseCount(Action action, Context<CountState> context) {
// 2.Effect handles click events
context.dispatch(CountActionCreator.updateCount());
}
Copy the code
- Code reduce.dart
import 'package:fish_redux/fish_redux.dart';
import 'action.dart';
import 'state.dart';
Reducer<CountState> buildReducer() {
return asReducer(
<Object, Reducer<CountState>>{
CountAction.updateCount: _updateCount,
},
);
}
/// Notify the View layer to update the interface
CountState _updateCount(CountState state, Action action) {
finalCountState newState = state.clone(); newState.. count = state.count +1; // 3. Core logic: Increment the number by 1 and return the newState object, at which point the page will refresh
return newState;
}
Copy the code
- Code state.dart
import 'package:fish_redux/fish_redux.dart';
// state manages the data for each page
class CountState implements Cloneable<CountState> {
int count;
@override
CountState clone() {
returnCountState() .. count = count; } } CountState initState(Map<String.dynamic> args) {
returnCountState().. count =0;
}
Copy the code
10. Code action.dart
import 'package:fish_redux/fish_redux.dart';
/// How many events a page has is defined in the enumeration
enum CountAction { updateCount,increase }
// Click the event handler class,
class CountActionCreator {
/// Click event. If you need to send parameters, you can place them in the payload field. Payload is of dynamic type
static Action increaseCount() {
return Action(CountAction.increase,payload: "Event Parameters");
}
static Action updateCount() {
return Action(CountAction.updateCount,payload: ["Optional"]); }}Copy the code
If you are a beginner, I believe you are confused at this point, what?
The principle of understanding
Dart button click event is triggereddispatch(CountActionCreator.increaseCount());
2. The framework automatically calls effect.dartbuildEffect()
Configure the event corresponding to the method and then passcontext.dispatch()
Continue to distribute the events
3. The reducer.dart is automatically called by the frameworkbuilderReducer()
Method corresponding to the configured time. Finally, update the count in state, return state, and the framework will recreate the layout bound to the count in state.
This enables coarse-grained control of the layout and only rebuilds the layout that needs to change, improving performance. At the same time, service logic can be written in Effect or reducer, which is generally written in reducer. Although there is several times more code, the subsequent complexity of the business, through this separation of UI and business logic can be better extended. Is it a little bit like MVC, MVP, MVVM? For example, Android typically requests an interface in onCreate(), and the page is refreshed when the request is successful, whereas fish-redux can be handled in effect.dart
Effect<CountState> buildEffect() {
// Combine effect
return combineEffects(<Object, Effect<CountState>>{
CountAction.increase: _onIncreaseCount,
Lifecycle.initState: _onCreate,
});
}
void _onCreate(Action action, Context<CountState> context){
// Interface request..
// After the request succeeds, the data is sent to the reducer using context.dispatchcontext.dispatch(...) ; }Copy the code
conclusion
Understanding the mechanics of Fish-Redux and knowing which methods are automatically called by the framework will save you from missteps in later coding.