ブログ一覧に戻る

Flutter: Adding custom platform-specific code (EventChannel)

西山 勇毅
Flutter iOS Swift Development Sensors

Flutter

Flutterアプリで、ネイティブ側(バックエンド)からイベントを発行してUI側(フロントエンド)を更新する方法について説明します。以前、Flutterプラグインの実装方法の一部としてEventChannelを実装する方法は書いたことがあります、今回はプラグインを使わないで同じ機能実装する方法です。

フロントエンドとバックエンドで通信を行う方法として、MethodChannelとEventChannel大きく2つの方法があります。今回は、EventChannelを使った方法を説明します。MethodChannelを使う方法は、公式ドキュメントに詳しく記述されています。何故か、EventChannelを使う方法は公式ページでは見当たらない。。

PlatformChannels

Backend (iOS)

AppDelegate.swiftのdidFinishLaunchingWithOptions内に、FlutterEventChannelを生成し、FlutterStreamHandlerを設定する。

let controller : FlutterViewController = window?.rootViewController as! FlutterViewController
let measurementEvent = FlutterEventChannel(name: "com.sample.app/event", binaryMessenger: controller.binaryMessenger)
measurementEvent.setStreamHandler(HomeStreamHandler())

FlutterStreamHandlerには、onListenとonCancelの2つのメソッドが必要。onListenで、イベントのコールバック(FlutterEventSink)を取得し、onCancelでリスナーを解除する。

public class HomeStreamHandler: NSObject, FlutterStreamHandler {

 var eventSink: FlutterEventSink?

 public func onListen(withArguments arguments: Any?, eventSink events: @escaping FlutterEventSink) -> FlutterError? {
  self.eventSink = events
  // TODO: イベントが発生したら、eventSink(Any)メソッドに任意の値を与えることで、UI側に値を引き渡すことができる。
  // NOTE: サポートしてデータ形式は、表1を参照してください。
  return nil
 }

 public func onCancel(withArguments arguments: Any?) -> FlutterError? {
   eventSink = nil
   return nil
 }
}

Frontend (Flutter)

フロントエンド側では、EventChannelを生成し、receiveBroadcastStreamでイベントを受信する。

import 'package:flutter/services.dart';
import 'dart:collection';

class _MyHomePageState extends State<MyHomePage> {
 static const eventChannel = const EventChannel('com.sample.app/event');
 StreamSubscription _onChangedSubscription;

 @override
 void initState() {
  // TODO: implement initState
  super.initState();
  this._onChangedSubscription = eventChannel.receiveBroadcastStream().listen((event) {
   // NOTE: eventはdynamicなので、送信元の型に応じてキャストが必要
   // NOTE: Dictionary型の場合、Mapになるかと思いきや、LinkedHashMapになっていた。
   var data = event as LinkedHashMap;
   var value = data['key'];
   setState((){
    // TODO: do something
   });
  });
 }

サポートされているデータ形式

Supported Data Types

参考資料

この記事をシェア