Foggy day

[Flutter] EventChannel - Android 본문

Flutter/Flutter 기타

[Flutter] EventChannel - Android

jinhan38 2023. 8. 29. 00:06

 

이번 포스팅에서는 EventChannel에 대해 알아보겠습니다.

 

EventChannel(이벤트채널)이란?

- 이벤트 채널은 플랫폼들이 이벤트 스트림을 사용해서 통신하는 방법입니다. 데이터 전송 방향은 Native -> Flutter입니다.

 

 

1. Dart EventChannel

2. Android EventChannel

 

 

 

1. Dart EventChannel

먼저 Dart 코드에서 이벤트 채널(스트림)을 등록해 보겠습니다. 

EventChannel 클래스를 생성해야 하는데 이때 생성자에 채널명을 넣어주세요. EventChannel 클래스의 receiveBroadcastStream 함수의 리턴 타입은 Stream이므로 listen 함수를 구현할 수 있습니다. listen 함수의 event에는 Native에서 전달한 값이 들어있습니다. 받아온 값은 전역변수인 eventValue에 할당했습니다.

cancelEventChannel 함수에서는 앞서 생성한 StreamSubscription을 cancel 하고 null 초기화했습니다. 

 

  final EventChannel eventChannel = const EventChannel('androidEventChannel');
  StreamSubscription? _streamSubscription;
  dynamic eventValue;

  void setEventChannel() {
    _streamSubscription = eventChannel
        .receiveBroadcastStream()
        .map<dynamic>((event) => event)
        .listen((event) {
      if (mounted) {
        setState(() {
          eventValue = event;
        });
      }
    });
  }

  void cancelEventChannel() {
    _streamSubscription?.cancel();
    _streamSubscription = null;
  }

 

 

 

2. Android EventChannel

네이티브에서는 커스텀 EventChannelHandler 클래스를 추가로 만들었습니다. 이 클래스는 EventChannel.StreamHandler를 상속받고 있습니다.

override한 onListen함수에서는 EventSink를 받을 수 있는데 EventSink를 사용해서 flutter에 데이터를 전달할 수 있습니다. 

 

import android.os.Handler
import android.os.Looper
import io.flutter.plugin.common.BinaryMessenger
import io.flutter.plugin.common.EventChannel

class EventChannelHandler(binaryMessenger: BinaryMessenger, name: String) : EventChannel.StreamHandler {
    var eventChannel: EventChannel? = null
    var eventSink: EventChannel.EventSink? = null

    init {
        eventChannel = EventChannel(binaryMessenger, name)
        eventChannel!!.setStreamHandler(this)
    }

    override fun onListen(arguments: Any?, events: EventChannel.EventSink?) {
        if (events != null) {
            eventSink = events
            events.success(arguments)
        }
    }

    override fun onCancel(arguments: Any?) {
        if (arguments != null) {
            sink(arguments)
        }
        eventChannel?.setStreamHandler(null)
        eventChannel = null
        eventSink = null
    }


    fun sink(value: Any) {
        Handler(Looper.getMainLooper()).post {
            eventSink?.success(value)
        }
    }
}

 

 

MainActivity에서는 위에서 만든 클래스를 생성하고, Flutter에서 입력한 Channel의 name과 동일한 name을 넣어줍니다. 그리고 타이머를 사용해서 2초에 한번씩 숫자를 증가시켜 줍니다.

import io.flutter.embedding.android.FlutterActivity
import io.flutter.embedding.engine.FlutterEngine
import kotlin.concurrent.timer

class MainActivity : FlutterActivity() {
    var eventChannelHandler: EventChannelHandler? = null
    var count = 0

    override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
        super.configureFlutterEngine(flutterEngine)
        eventChannelHandler = EventChannelHandler(flutterEngine.dartExecutor.binaryMessenger, "androidEventChannel")

        timer(period = 2000) {
            count++
            eventChannelHandler?.sink(count)
        }
    }

    override fun onDestroy() {
        eventChannelHandler?.onCancel(null)
        eventChannelHandler = null
        super.onDestroy()
    }

}