功能 | 库 | GitHub地址 |
---|---|---|
Provider | provider | rrousselGit/provider |
scope_model | scoped_model | brianegan/scoped_model |
Redux | flutter_redux | brianegan/flutter_redux |
BLoc | flutter_bloc | felangel/bloc |
RxDart | rxdart | ReactiveX/rxdart |
Mobx | flutter_mobx | mobxjs/mobx.dart |
scope_model
model.dart
import 'package:scoped_model/scoped_model.dart';
class CountModel extends Model{
int _count = 0;
get count => _count;
void increment(){
_count++;
notifyListeners();
}
CountModel of(context) =>
ScopedModel.of<CountModel>(context);
}
main.dart
import 'package:flutter/material.dart';
import 'package:scoped_model/scoped_model.dart';
import 'model/index.dart';
void main() => runApp(new MyApp());
class MyApp extends StatelessWidget {
//创建顶层状态
CountModel countModel = CountModel();
@override
Widget build(BuildContext context) {
return ScopedModel<CountModel>(
model: countModel,
child: new MaterialApp(
title: 'ScopedModel Demo',
theme: new ThemeData(
primarySwatch: Colors.blue,
),
home: FirstScreen(),
),
);
}
}
// ----------------------------------------------------------
class FirstScreen extends StatefulWidget {
@override
FirstScreenState createState() => FirstScreenState();
}
class FirstScreenState extends State<FirstScreen> {
//静态获取model用法实例
Model getModel(BuildContext context){
//直接使用of
final countModel = ScopedModel.of<CountModel>(context, rebuildOnChange: true);
//使用CountModel中重写的of
final countModel2 = CountModel().of(context);
countModel.increment();
countModel2.increment();
return countModel;
// return countMode2;
}
@override
Widget build(BuildContext context) {
return ScopedModelDescendant<CountModel>(
builder: (context,child,model){
return Scaffold(
appBar: AppBar(
title: Text('Top Screen'),
),
body: Center(
child: Text(
model.count.toString(),
style: TextStyle(fontSize: 48.0),
),
),
floatingActionButton: FloatingActionButton(
onPressed: () {
Navigator.of(context).push(MaterialPageRoute(builder: (BuildContext context){
return SecondScreen(title: "Under Screen",);
}));
},
child: Icon(Icons.forward),
),
);
},
);
}
}
// ----------------------------------------------------------
class SecondScreen extends StatefulWidget {
SecondScreen({Key? key, required this.title}) : super(key: key);
final String title;
@override
SecondScreenState createState() => new SecondScreenState();
}
class SecondScreenState extends State<SecondScreen> {
@override
Widget build(BuildContext context) {
return ScopedModelDescendant<CountModel>(builder: (context, child, model) {
return Scaffold(
appBar: new AppBar(
title: new Text(widget.title),
),
body: new Center(
child: new Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
new Text(
'You have pushed the button this many times:',
style: TextStyle(fontSize: 20.0),
),
Text(
"${model.count}",
style: TextStyle(fontSize: 36.0),
),
],
),
),
floatingActionButton: new FloatingActionButton(
onPressed: () => model.increment(),
tooltip: 'Increment',
child: new Icon(Icons.add),
), // This trailing comma makes auto-formatting nicer for build methods.
);
},
// rebuildOnChange: false,
);
}
}
flutter_redux
简单代码
import 'package:flutter/material.dart';
import 'package:flutter_redux/flutter_redux.dart';
import 'package:redux/redux.dart';
enum Actions { Increment }
int counterReducer(int state, dynamic action) {
if (action == Actions.Increment) {
return state + 1;
}
return state;
}
void main() {
final store = Store<int>(counterReducer, initialState: 0);
runApp(FlutterReduxApp(
title: 'Flutter Redux Demo',
store: store,
));
}
class FlutterReduxApp extends StatelessWidget {
final Store<int> store;
final String title;
FlutterReduxApp({Key? key, required this.store, required this.title}) : super(key: key);
@override
Widget build(BuildContext context) {
return StoreProvider<int>(
store: store,
child: MaterialApp(
theme: ThemeData.dark(),
title: title,
home: Scaffold(
appBar: AppBar(
title: Text(title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
StoreConnector<int, String>(
converter: (store) => store.state.toString(),
builder: (context, count) {
return Text(
'The button has been pushed this many times: $count',
style: Theme.of(context).textTheme.bodyText1,
);
},
)
],
),
),
floatingActionButton: StoreConnector<int, VoidCallback>(
converter: (store) {
return () => store.dispatch(Actions.Increment);
},
builder: (context, callback) {
return FloatingActionButton(
// Attach the `callback` to the `onPressed` attribute
onPressed: callback,
tooltip: 'Increment',
child: Icon(Icons.add),
);
},
),
),
),
);
}
}
示例
- Simple example - a port of the standard “Counter Button” example from Flutter
- Github Search - an example of how to search as a user types, demonstrating both the Middleware and Epic approaches.
- Todo app - a more complete example, with persistence, routing, and nested state.
- Timy Messenger - large open source app that uses flutter_redux together with Firebase Firestore.
Companion Libraries
- flipperkit_redux_middleware - Redux Inspector (use Flutter Debugger) for Flutter Redux apps
- flutter_redux_dev_tools - Redux应用程序的 Time Travel开发调试工具
- redux_persist - 持久化状态
- flutter_redux_navigation - 使用redux事件进行导航
- flutter_redux_gen - VS代码扩展以生成redux代码