Flutter基礎-036-事件匯流排EventBus

天色將變發表於2021-03-01

在Android原生中,有廣播可以進行跨頁面傳遞資料。 Flutter中我們可以自定義一個事件匯流排,實現跨頁面傳遞資料。 步驟

  • 定義一個單例類
  • 新增一個Map<String ,CallBack>變數,儲存監聽的事件名和對應的回撥方法。
  • 新增on方法,用於向map中新增事件。
  • 新增off方法,用於從map中移除事件監聽。
  • 定義emit方法,用於事件源發射事件。

事件匯流排:

//訂閱者回撥簽名
typedef void EventCallback(arg);

class EventBus {
  //私有建構函式
  EventBus._internal();

  //儲存單例
  static EventBus _singleton = new EventBus._internal();

  //工廠建構函式
  factory EventBus()=> _singleton;

  //儲存事件訂閱者佇列,key:事件名(id),value: 對應事件的訂閱者
  var _emap = new Map<String, EventCallback>();

  //新增訂閱者
  void on(eventName, EventCallback f) {
    if (eventName == null || f == null) return;
    _emap[eventName]=f;
  }

  //移除訂閱者
  void off(eventName) {
    _emap[eventName] = null;
  }

  //觸發事件,事件觸發後該事件所有訂閱者會被呼叫
  void emit(eventName, [arg]) {
    var f = _emap[eventName];
    f(arg);
  }
}
複製程式碼

測試頁面:


class EventBusTest extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'RaisedButton',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(title: 'RaisedButton'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);

  final String title;

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  // 獲取事件匯流排
  var bus = new EventBus();
  int index = 1;
  String text = '';

  @override
  void initState() {
    super.initState();
    // 新增監聽,模仿不同頁面新增事件監聽
    bus.on("key0", (parmas){text=parmas.toString();});
    bus.on("key1", (parmas){text=parmas.toString();});
    bus.on("key2", (parmas){text=parmas.toString();});
  }

  @override
  void dispose() {
    super.dispose();
    //widget關閉時 刪除監聽
    bus.off("key0");
    bus.off("key1");
    bus.off("key2");
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        //導航欄
        title: Text("App Name"),
        actions: <Widget>[
          //導航欄右側選單
          IconButton(icon: Icon(Icons.share), onPressed: () {}),
        ],
      ),
      body: Center(
        child: Text(text),
      ),
      floatingActionButton: FloatingActionButton(
        //懸浮按鈕
        child: Text("emit"),
        onPressed: _onAdd,// 點選呼叫方法
      ),
    );
  }


  void _onAdd() {
    index++;
    setState(() {
      // 傳送事件
      bus.emit(getNameByIndex(index), index);
    });
  }

  String getNameByIndex(index){
    if(index%3==0){
      return 'key0';
    }
    if(index%3==1){
      return 'key1';
    }
    if(index%3==2){
      return 'key2';
    }
  }
}

複製程式碼

相關文章