flutter一個重要的特性就是組件化。組件分爲兩種狀態,一種是StatefulWidget有狀態組件,一種是StatelessWidget無狀態組件。 無狀態組件不能更新狀態,有狀態組件具備相似刷新的機制,可更改狀態。
功能模塊均可以經過繼承兩種狀態組件實現功能模塊封裝。組件間通訊,通常存在一下兩種關係。app
//父組件 class ParentWidget extends StatefulWidget { final String title; ParentWidget({Key key,this.title}):super(key:key); @override State<StatefulWidget> createState() { return new ParentWidgetState(); } } class ParentWidgetState extends State<ParentWidget> { Color containerBg = Colors.orange;
//回調函數 void changeBackgroundColor(Color newColor){ setState(() { containerBg = newColor;//修改狀態 }); } @override Widget build(BuildContext context) { return new Scaffold( appBar: new AppBar( title: new Text(widget.title), ), body: new Center( child: new GestureDetector( onTap: (){ changeBackgroundColor(Colors.orange); }, child: new Container( width: 300, height: 300, color: containerBg, alignment: Alignment.center, child: new Row( mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: <Widget>[ new childrenA(childrenACallBack: changeBackgroundColor), new childrenB(childrenBCallBack: changeBackgroundColor), ], ), ), ) ), ); } } //子組件(組件A) class childrenA extends StatelessWidget {
//定義接收父類回調函數的指針
final ValueChanged<Color> childrenACallBack; childrenA({Key key,this.childrenACallBack}):super(key:key);
@override Widget build(BuildContext context) { return new GestureDetector( onTap: (){
//調用回調函數傳值 childrenACallBack(Colors.green); }, child: new Container( width: 80, height: 80, color: Colors.green, child: new Text('ChildrenA'), ), ); } } //子組件(組件B) class childrenB extends StatelessWidget { final ValueChanged<Color> childrenBCallBack; childrenB({Key key,this.childrenBCallBack}):super(key:key); @override Widget build(BuildContext context) { return new GestureDetector( onTap:(){ childrenBCallBack(Colors.red); }, child: new Container( width: 80, height: 80, color: Colors.red, child: new Text('ChildredB'), ), ); } }
功能實現
less
InheritedWidget 數據共享ide
import 'package:flutter/material.dart'; void main() => runApp(MyApp()); class MyApp extends StatelessWidget { // This widget is the root of your application. @override Widget build(BuildContext context) { return MaterialApp( title: 'Flutter Demo', theme: ThemeData( primarySwatch: Colors.blue, ), home: new InheritedWidgetTestContainer(), ); } } //模型數據 class InheritedTestModel { final int count; const InheritedTestModel(this.count); } //哨所(自定義InheritedWidget類) class InheritedContext extends InheritedWidget { //構造函數 InheritedContext({ Key key, @required this.inheritedTestModel, @required this.increment, @required this.reduce, @required Widget child }):super(key:key,child:child); //變量 final InheritedTestModel inheritedTestModel; final Function() increment; final Function() reduce; //靜態方法 static InheritedContext of(BuildContext context){ InheritedContext contexts = context.inheritFromWidgetOfExactType(InheritedContext); return context.inheritFromWidgetOfExactType(InheritedContext); } //是否重建取決於Widget組件是否相同 @override bool updateShouldNotify(InheritedContext oldWidget) { return inheritedTestModel != oldWidget.inheritedTestModel; } } class TestWidgetA extends StatelessWidget { @override Widget build(BuildContext context) { final inheritedContext = InheritedContext.of(context); return new Padding( padding: const EdgeInsets.only(left: 10.0,top: 10.0,right: 10.0), child: new RaisedButton( textColor: Colors.black, child: new Text('+'), onPressed:inheritedContext.increment ), ); } } class TestWidgetB extends StatelessWidget { @override Widget build(BuildContext context) { final inheritedContext = InheritedContext.of(context); return new Padding( padding: const EdgeInsets.only(left: 10,top: 10,right: 10.0), child: new RaisedButton( textColor: Colors.black, child: new Text('-'), onPressed: inheritedContext.reduce ), ); } } class TestWidgetC extends StatelessWidget { @override Widget build(BuildContext context) { final inheritedContext = InheritedContext.of(context); final inheritedTestModel = inheritedContext.inheritedTestModel; return new Padding( padding: const EdgeInsets.only(left: 10.0,top: 10.0,right: 10.0), child: new RaisedButton( textColor: Colors.black, child: new Text('${inheritedTestModel.count}'), onPressed: (){ }, ), ); } } class InheritedWidgetTestContainer extends StatefulWidget { @override State<StatefulWidget> createState() { return new InheritedWidgetTestContainerState(); } } class InheritedWidgetTestContainerState extends State<InheritedWidgetTestContainer> { InheritedTestModel _inheritedTestModel; _initData(){ _inheritedTestModel = new InheritedTestModel(0); } @override void initState() { _initData(); super.initState(); } _incrementCount(){ setState(() { _inheritedTestModel = new InheritedTestModel(_inheritedTestModel.count + 1); }); } _reduceCount(){ setState(() { _inheritedTestModel = new InheritedTestModel(_inheritedTestModel.count - 1); }); } @override Widget build(BuildContext context) { return new InheritedContext( inheritedTestModel: _inheritedTestModel, increment: _incrementCount, reduce: _reduceCount, child: new Scaffold( appBar: new AppBar( title: new Text('InheritedWidgetTest'), ), body: new Center( child: new Column( children: <Widget>[ new TestWidgetA(), new TestWidgetB(), new TestWidgetC(), ], ), ) ), ); } }
使用場景
通常用於父組件對子組件的跨組件傳值。函數
//父組件 class ParentWidget extends StatefulWidget { @override State<StatefulWidget> createState() { return new ParentWidgetState(); } } class ParentWidgetState extends State<ParentWidget> { @override Widget build(BuildContext context) { return new Scaffold( appBar: new AppBar( title: new Text('組件化'), ), body: new Center( child: new Container( color: Colors.grey, width: 200, height: 200, child: new Row( mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: <Widget>[ new SubWidgetA(key: subAkey), new SubWidgetB(key: subBkey) ], ), ), ), ); } } //子組件A class SubWidgetA extends StatefulWidget { SubWidgetA({Key key}):super(key:key); @override State<StatefulWidget> createState() { return new SubWidgetAState(); } } class SubWidgetAState extends State <SubWidgetA> { Color _backgroundColors = Colors.red;//紅色 void updateBackGroundColors(Color colos){ setState(() { _backgroundColors = colos; }); } @override Widget build(BuildContext context) { return new GestureDetector( onTap: (){ subBkey.currentState.updateBackGroundColors(Colors.blue); setState(() { _backgroundColors = Colors.red; }); }, child: new Container( width: 80, height: 80, color:_backgroundColors, alignment: Alignment.center, child: new Text('SubWidgetA'), ), ); } } //子組件B class SubWidgetB extends StatefulWidget { SubWidgetB({Key key}):super(key:key); @override State<StatefulWidget> createState() { // TODO: implement createState return new SubWidgetBState(); } } class SubWidgetBState extends State<SubWidgetB> { Color _backgroundColors = Colors.green;//綠色 void updateBackGroundColors(Color colos){ setState(() { _backgroundColors = colos; }); } @override Widget build(BuildContext context) { return new GestureDetector( onTap: (){ subAkey.currentState.updateBackGroundColors(Colors.blue); setState(() { _backgroundColors = Colors.green; }); }, child: new Container( width: 80, height: 80, color: _backgroundColors, alignment: Alignment.center, child: new Text('SubWidgetB'), ), ); } }
class ValueNotifierData extends ValueNotifier<String> { ValueNotifierData(value) : super(value); }
_WidgetOne
,包含一個ValueNotifierData的實例。class _WidgetOne extends StatefulWidget { _WidgetOne({this.data}); final ValueNotifierData data; @override _WidgetOneState createState() => _WidgetOneState(); }
_WidgetOneState
中給ValueNotifierData實例添加監聽。@override initState() { super.initState(); widget.data.addListener(_handleValueChanged); info = 'Initial mesage: ' + widget.data.value; } void _handleValueChanged() { setState(() { info = 'Message changed to: ' + widget.data.value; });
ValueNotifierCommunication
組件中實例化_WidgetOne
,能夠經過改變ValueNotifierData
實例的value來觸發_WidgetOneState
的更新。@override Widget build(BuildContext context) { ValueNotifierData vd = ValueNotifierData('Hello World'); return Scaffold( appBar: AppBar(title: Text('Value Notifier Communication'),), body: _WidgetOne(data: vd), floatingActionButton: FloatingActionButton(child: Icon(Icons.refresh),onPressed: () { vd.value = 'Yes'; }), ); }
import 'package:event_bus/event_bus.dart';
event_bus用法。組件化
新建消息監測類ui
import 'package:event_bus/event_bus.dart'; EventBus eventBus = new EventBus(); class TransEvent{ String text; TransEvent(this.text); }
監測類變化this
eventBus.on<TransEvent>().listen((TransEvent data) => show(data.text)); void show(String val) { setState(() { data = val; }); }
觸發消息變化spa
eventBus.fire(new TransEvent('$inputText'));