Fish-Redux Developing flutter (PART 1)
In the previous two articles, we looked at fish-Redux and implemented simple functions. This time we’ll look at some other features of Fish-Redux. Take a look at the resulting graph:
1 Make a list using Component and Adapter
1.1 Create a list page and define data
The page creation process is omitted as before. I created a page called List with the following results
Add our page to app.dart. Dart is modified as follows
Widget createApp() {
final AbstractRoutes routes = PageRoutes(
pages: <String, Page<Object.dynamic> > {'entrance_page': EntrancePage(),
'grid_page': GridPage(),
'list_page':ListPage(), // Add our new page here});/ / to omit...
Copy the code
Then implement a page jump from the Grid page to the page. Create the action, dispatch the action in view, receive the action in effect, and jump to the page
1.2 create a component
Then we create a Component under the List package for each item of the list.
The first step is to create a Component from the plug-in
First create a package named item, then create the FishReduxTemplate under item, this time selecting Component.
Dart in the component is similar to Page. Dart in the page.
The second step defines the component data and UI
We give state three fields: Type (icon shape), title (title), and Content (content). Dart: modify /list/item/state.dart as follows
import 'package:fish_redux/fish_redux.dart';
class ItemState implements Cloneable<ItemState> {
int type;
String title;
String content;
ItemState({this.type, this.title, this.content});
@override
ItemState clone() {
returnItemState() .. type = type .. title = title .. content = content; } } ItemState initState(Map<String.dynamic> args) {
return ItemState();
}
Copy the code
Then we implement the view of item, using the state data above and displaying different ICONS depending on type (see comments). / list/item/the dart is as follows
import 'package:fish_redux/fish_redux.dart';
import 'package:flutter/material.dart';
import 'action.dart';
import 'state.dart';
Widget buildView(ItemState state, Dispatch dispatch, ViewService viewService) {
return Container(
margin: EdgeInsets.fromLTRB(0.0.0.10),
height: 120.0,
color: Colors.white,
child: GestureDetector(
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
// Left icon
Container(
padding: const EdgeInsets.only(right: 5.0),
child: Center(
child: Icon(
// Different types display different ICONS
state.type == 1 ? Icons.account_circle : Icons.account_box,
size: 50.0,),),),/ / on the right side
Expanded(
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
// The header section
Container(
height: 30,
child: Text(
state.title,
style: TextStyle(fontSize: 22.0),),),// Content section
Text(
state.content,
style: TextStyle(fontSize: 16.0),
),
],
),
),
],
),
onTap: () {
//todo click events},),); }Copy the code
1.3 Associating Components with Web Pages
Component concludes. Next we use the components in the list.
Step 1 Create the Adapter
First, store the State data of each Item in the State of List. / list/state. The dart/as follows
import 'package:fish_demo/list/item/state.dart';
import 'package:fish_redux/fish_redux.dart';
class ListState implements Cloneable<ListState> {
List<ItemState> items; // Save item state
@override
ListState clone() {
returnListState() .. items = items; } } ListState initState(Map<String.dynamic> args) {
return ListState();
}
Copy the code
Then we associate the list with the item, and we use one of the fish-Redux components called adapter. Create FishReduxTemplate with the plugin in the list package. Then select the DynamicFlowAdapter and uncheck all other boxes. Name it list as follows
The second step implements the Connector
We see that the default Adapter code has two classes ready for us: a ListAdapter and a _ListConnector. In the ListAdapter, we configure the components to be associated, that is, add the components to the pool. And list and component data adaptation by implementing a connector. The completed /list/adapter.dart is as follows
import 'package:fish_demo/list/state.dart';
import 'package:fish_redux/fish_redux.dart';
import 'item/component.dart';
import 'item/state.dart';
class ListAdapter extends DynamicFlowAdapter<ListState> {
ListAdapter()
: super(
pool: <String, Component<Object> > {"MyItem": ItemComponent(), // Reference the component
},
connector: _ListConnector(),
);
}
class _ListConnector extends ConnOp<ListState.List<ItemBean>> {
@override
List<ItemBean> get(ListState state) {
// Check whether the items in ListState are empty
if(state.items? .isNotEmpty ==true) {
// If not empty, convert item data to a list of ItemBeans
return state.items
.map<ItemBean>((ItemState data) => ItemBean('MyItem', data))
.toList(growable: true);
}else{
// If it is empty, return the empty list
return<ItemBean>[]; }}@override
void set(ListState state, List<ItemBean> items) {
// The process of modifying the ItemBean changes to the item state
if(items? .isNotEmpty ==true) {
state.items = List<ItemState>.from(
items.map<ItemState>((ItemBean bean) => bean.data).toList());
} else{ state.items = <ItemState>[]; }}@override
subReducer(reducer) {
// TODO: implement subReducer
return super.subReducer(reducer); }}Copy the code
The third step is to add the Adapter to the dependencies of the list page
We open the Page file of the List page and add adapter to the dependencies of the page. The following
import 'package:fish_demo/list/adapter.dart';/ / note 1
import 'package:fish_redux/fish_redux.dart' hide ListAdapter;/ / note 1
import 'effect.dart';
import 'reducer.dart';
import 'state.dart';
import 'view.dart';
class ListPage extends Page<ListState.Map<String.dynamic>> {
ListPage()
: super(
initState: initState,
effect: buildEffect(),
reducer: buildReducer(),
view: buildView,
dependencies: Dependencies<ListState>(
adapter: NoneConn<ListState>() + ListAdapter(),/ / note 2
slots: <String, Dependent<ListState>>{
}),
middleware: <Middleware<ListState>>[
],);
}
Copy the code
I’ve made two notes about the code above.
Note 1: We are referring to the custom ListAdapter, not the ListAdapter class that comes with Fish-redux. (Should have known the name when not called ListAdapter…)
Note 2: The “plus” used here is the fish-redux overloaded operator. The latter is our custom Adapter, and since we no longer need the connector on the outer layer, the former passes in a NoneConn.
Step 4 Lists the UI
Dart: /list/view.dart: /list/view.dart: / list/the dart is as follows
import 'package:fish_redux/fish_redux.dart';
import 'package:flutter/material.dart';
import 'state.dart';
Widget buildView(ListState state, Dispatch dispatch, ViewService viewService) {
ListAdapter adapter = viewService.buildAdapter(); / / create the adapter
return Scaffold(
appBar: new AppBar(
title: new Text('List page'),
),
body: Container(
child: ListView.builder(
itemBuilder: adapter.itemBuilder, // Configure adapter to list
itemCount: adapter.itemCount, //))); }Copy the code
1.4 With fake data
Finally, let’s add some fake data to the List page to see what happens. We’ve already learned how to do that
- Effect creates dummy data when the page is initialized
- Effect sends an action with fake data
- Reducer received action and updated state with dummy data
This time the action takes parameters. Post the code
Let’s run it and see what it looks like
2 Use global Store to change the theme
This time let’s touch store. It is responsible for managing global state, as demonstrated by theme colors.
2.1 Creating a Global State
Whereas previously pages and components were created using the plug-in template, Store created them manually. Create a package called Store. Dart is then created, which we use to hold global state. In this case, save the theme color. / store/state. The dart is as follows
import 'dart:ui';
import 'package:fish_redux/fish_redux.dart';
abstract class GlobalBaseState {
Color get themeColor;
set themeColor(Color color);
}
class GlobalState implements GlobalBaseState.Cloneable<GlobalState> {
@override
Color themeColor;
@override
GlobalState clone() {
returnGlobalState(); }}Copy the code
Notice that we define an abstract class GlobalBaseState that contains the themeColor field. We’ll let all page states inherit it later. We also wrote an implementation class GlobalState, which is the GlobalState.
2.2 create the store
Dart is the App store. Dart is the App store. / store/store. The dart is as follows
import 'package:fish_redux/fish_redux.dart';
import 'state.dart';
class GlobalStore {
static Store<GlobalState> _globalStore;
static Store<GlobalState> getstore => _globalStore ?? = createStore<GlobalState>(GlobalState(), buildReducer()); }Copy the code
You can see that the Store holds global state, and it can also have a Reducer to handle events. Next we define its actions and reducer.
2.3 Create Store Actions and reducer
Dart is created to define an event that changes the color of the theme. / store/action. The dart is as follows
import 'package:fish_redux/fish_redux.dart';
enum GlobalAction { changeThemeColor }
class GlobalActionCreator {
static Action onchangeThemeColor() {
return constAction(GlobalAction.changeThemeColor); }}Copy the code
Dart is created to receive events and change the GlobalState theme color. Dart is as follows (here we have the theme color switch back and forth between blue and green)
import 'dart:ui';
import 'package:fish_redux/fish_redux.dart';
import 'package:flutter/material.dart' hide Action;
import 'action.dart';
import 'state.dart';
Reducer<GlobalState> buildReducer() {
return asReducer(
<Object, Reducer<GlobalState>>{
GlobalAction.changeThemeColor: _onchangeThemeColor,
},
);
}
GlobalState _onchangeThemeColor(GlobalState state, Action action) {
final Color color =
state.themeColor == Colors.green ? Colors.blue : Colors.green;
returnstate.clone().. themeColor = color; }Copy the code
And then the whole store is written. You and your family
2.4 inheritance GlobalBaseState
We inherited GlobalBaseState state from all pages and set the title bar color to themeColor in the page view. There are three interfaces (entrance, grid and list) that need to be modified. Take the list page as an example, the first one is /list/state.dart
Then/list/view. The dart
The other two pages are shown in the same way.
2.5 associated state
How do you relate individual page states to the global GlobalState? We need to configure the visitor in app.dart. In this case, we determine whether the page inherits GlobalBaseState and then associate the page with the global Store, meaning that the page’s state changes with the global state update. The modified app.dart is as follows
Widget createApp() {
final AbstractRoutes routes = PageRoutes(
pages: <String, Page<Object.dynamic> > {'entrance_page': EntrancePage(),
'grid_page': GridPage(),
'list_page': ListPage(),
},
visitor: (String path, Page<Object.dynamic> page) {
/// The condition Page is met<T>, T is a subclass of GlobalBaseState.
if (page.isTypeof<GlobalBaseState>()) {
// set up a one-way data connection for AppStore driver PageStore
/// 1. Parameter 1 AppStore
/// 2. Parameter 2 How should pagestore. state change when AppStore
page.connectExtraStore<GlobalState>(
GlobalStore.store, (Object pagestate, GlobalState appState) {
final GlobalBaseState p = pagestate;
if(p.themeColor ! = appState.themeColor) {if (pagestate is Cloneable) {
final Object copy = pagestate.clone();
final GlobalBaseState newState = copy;
newState.themeColor = appState.themeColor;
returnnewState; }}returnpagestate; }); }});// The following omission...
}
Copy the code
2.6 Triggering a Theme Change
Finally, I want to switch the theme color by clicking item on the List page.
The first step
Dart: /list/item/action.dart
import 'package:fish_redux/fish_redux.dart';
enum ItemAction { action, onThemeChange }
class ItemActionCreator {
static Action onAction() {
return const Action(ItemAction.action);
}
static Action onThemeChange() {
return constAction(ItemAction.onThemeChange); }}Copy the code
The second step
We send this event when the item clicks. / list/item/the dart is as follows
Widget buildView(ItemState state, Dispatch dispatch, ViewService viewService) {
return Container(
margin: EdgeInsets.fromLTRB(0.0.0.10),
height: 120.0,
color: Colors.white,
child: GestureDetector(
child: Row(
/ / to omit...), onTap: () { dispatch(ItemActionCreator.onThemeChange()); },),); }Copy the code
The third step
Receives the event in Effect and sends the global change theme color event we defined earlier. / list/item/effect. The dart is as follows
import 'package:fish_demo/store/action.dart';
import 'package:fish_demo/store/store.dart';
import 'package:fish_redux/fish_redux.dart';
import 'action.dart';
import 'state.dart';
Effect<ItemState> buildEffect() {
return combineEffects(<Object, Effect<ItemState>>{
ItemAction.action: _onAction,
ItemAction.onThemeChange: _onThemeChange,
});
}
void _onAction(Action action, Context<ItemState> ctx) {
}
void _onThemeChange(Action action, Context<ItemState> ctx) {
GlobalStore.store.dispatch(GlobalActionCreator.onchangeThemeColor());
}
Copy the code
Finally run to see the effect: step by step into the list page, click item several times, the theme color changes accordingly. Return to the parent page, the theme color has also been changed.
conclusion
So far, we have seen some basic uses of fish-Redux. Since students on the client side have little contact with redux framework, they should change their thinking, read more documents and think more when using it.
Project source github.com/Jegaming/Fi…
🤗 If my content is helpful to you, welcome to like, comment, forward, favorites.