Weekly Flutter

[Platform integration] 2. Event Channel 사용방법

kikitkaka 2023. 3. 8. 15:45

이전포스트에서 Method Channel을 다루면서 플러터가 네이티브의 OS정보를 가져올 수 있는 방법은 3가지가 있다고 설명 했었습니다.

  1. Method Channel : 단발적, 표준 메세지 코덱을 사용합니다
  2. Event Channel : EventChannel은 stream 데이터가 필요할때 사용합니다.
  3. Basic Message Channel: Method Channel보다 더 기본적. 코덱을 커스텀하기위해 사용하는 방법입니다

MethodChannel을 사용하면 단발적인 요청으로 그에 대한 비동기적 응답을 얻을 수 있었습니다.

이번에 살펴볼 EventChannel은 단발적인 요청과 응답이 아니라, 채널이 열려있는동안 이벤트가 발생하면 지속적으로 데이터를 받아서 사용할 수 있도록 해줍니다.

 

  • Event Channel은 뭘 하는 녀석일까?

Flutter.dev에서 Event Channel 은 event stream을 사용하는 플랫폼 플러그인과 소통하는 이름지어진 채널' 이라고 설명하고 있습니다.

event stream이 뭘까요?

event는 어떤 동작에 의해 실행되는 사건을 의미하고,

stream은 줄기, 흐름, 연속 이라는 뜻을 가진 단어입니다. 이에 걸맞게 프로그래밍에서도 stream은 시간이 지남에 따라 사용할 수 있게 되는 일련의 데이터 요소를 가리키는 수많은 방식에서 쓰이고 있습니다.

즉 event stream을 사용한다는것은 어떤 동작에 의해 실행되는 사건을 단발적으로가 아니라, 시간이 지남에따라 생기는 데이터의 흐름을 처리하는 것 이라고 할 수 있겠습니다. 

 

EventChannel을 사용하면 채널이 열려있는동안 Listener는 구독하는 객체의 변화를 계속 비동기적으로 전달받을 수 있게 됩니다.

전달받은 이벤트는 이벤트 헨들러를 통해 처리되게 되고. 이때 이벤트 헨들러는 옵저버 패턴에서 관찰자(Observer)역할을 수행하게 됩니다.

옵저버패턴은 Subject 와 Observer 로 구성되면서, 다수의 Observer 들이 하나의 Subject 를 구독하고 Subject 에서 Observer 들에게 알림을줄수있는 디자인 패턴을 말합니다.

스트림은 데이터의 흐름을 제공하고, 이를 감지하는 관찰자는 스트림에서 발생하는 이벤트를 처리하는 역할을 하게 되는 것이지요.

 

EventChannel도 앞서 설명했던 MethodChannel처럼 Flutter코드를 작성하고, 네이티브 코드를 작성해주면 됩니다.

Flutter코드와 네이티브코드에서 모두 같은 채널명으로 채널을 열고, 동작시킬 메서드의 이름을 작성하고 상응되는 메서드 코드를 작성해준다는 점에서 MethodChannel과 사용방식이 거의 같아요. 다만 MethodChannel은 단발성으로 요청을 보내고 응답을 받았다면,

EventChannel은 stream형식이기 때문에 한번 응답받고 종료되는것이 아니라, 계속 event를 구독하고 있으면서(listen) 새로운 이벤트가 왔을때 등록해둔 동작할 수 있도록 listener를 등록해줘야 한다는 것이 다릅니다.

 

Event Channel도 MethodChannel과 마찬가지로 전송되기전에 binary로 인코드 되며, 전달받은 코드는 dart 값들로 디코드 됩니다. 이때 사용되는 MethodCodec에는 JSONMethodCodec,StandardMethodCodec 이 있는데, 플러터코드와 플랫폼코드에서 서로 호환 가능한 코덱을 사용해야 한다고 합니다.

 

  • 구현예시를 보면..

간단히 과정을 설명해보자면

1. Flutter코드에서 EventChannel을 통해 recevie() 해주고,

2. 코틀린코드의 EventChannel에 StreamHandler를 등록해주면 onListen()에서 arguments를 받을 수 있고 EventChannel.EventSink를 통해 Dart의 Stream에 결과를 반환할 수 있습니다.

 

요즘 kwj님이 작업해주신 딥링크 작업을 전달받아 코드를 보고 있는데요, eventChannel로 딥링크 이벤트를 받아서 처리하는 부분의 코드를 가져왔습니다.🥹(감사합니다..!)

딥링크 관련 데이터는 네이티브가 가지고있고, 플러터에서 이 이벤트를 플러터로 가져와서 사용해야합니다.

네이티브에서 딥링크 이벤트가 발생하게되면 이를 구독하고있던 플러터 Listener들에게 이 이벤트가 전달되는 방식으로 동작하고 있었습니다.

 

먼저 네이티브코드중 코틀린코드를 보겠습니다.

핸들러는 로직을 넣어주는 객체이며, 생성한 채널을 스트림에 연결하여 스트림안에 핸들러를 넘겨주는 구조로 이벤트 채널이 작동 됩니다. StreamHandler에 스트림에는 변화가 생겼을때 구독중인 옵저버들에게 실행시킬 핸들러를 등록하고 이 안에서 onListen, onCancel을 구현해줘야합니다

val eventChannel =
                EventChannel(
                    flutterEngine.dartExecutor.binaryMessenger,
                    "test/event/deeplink"
                )
            eventChannel.setStreamHandler(object : EventChannel.StreamHandler {
                override fun onListen(arguments: Any?, eventSink: EventChannel.EventSink) {
                    deeplinkEventSink = eventSink
                }

                override fun onCancel(arguments: Any?) {
                }
            })

 

Flutter코드에서 이벤트채널을 구독하고 이벤트가 왔을때 실행시킬 코드를 작성해준다.

이 채널에서 발생하는 이벤트를 받을 수 있도록 broadcast stream을 생성해줍니다.

BroadcaseStream이기때문에 listener를 여러개 붙일 수 있습니다.

stream.listen으로 이 스트림을 구독합니다. listen에 데이터가있을때, 에러가 발생했을때, 구독이끝났을때 실행시킬 handler를 등록할 수 있습니다. 이 스트림에서 발생하는 이벤트마다 구독자의 onData 핸들러가 불려지고, onData가 null이면 아무일도 일어나지 않습니다.

이 스트림에서 에러가 발생하면 onError 핸들러가 불려지고, stacktrace도 사용할 수 있습니다.

StreamSubscription<T> **listen**(void onData(T event)?,
      {Function? onError, void onDone()?, bool? cancelOnError});
static const _eventChannelName = 'test/event/deeplink';
  static const _eventChannel = EventChannel(_eventChannelName);

_stream = _eventChannel.receiveBroadcastStream(); // broadcastStream을 생성해준다.
    _stream!.listen((_) async {
    // 이제 스트림데이터가 들어오면 구독하고있던 옵저버에 데이터가 전달되고 등록해둔 콜백이 실행된다
      WidgetsBinding.instance.addPostFrameCallback(
        (_) async {
          await _initializeDeeplinkAndPopToMain();
          _startProcess();
        },
      );
    });

 

구현코드들을 보면 간단하지만 event channel을 공부하면서 event stream, 옵저버 패턴도 더 공부해볼 수 있었습니다.

3번 Message Channel은 Method Channel과 유사하지만 코덱을 커스텀할 수 있는 방법이기때문에 차후에 이 포스트에 업로드를 하도록 하고 다음에는 다른 내용으로 뵙도록 하겠습니다..!

읽어주셔서 감사합니다

 

 

 

- 참고한 사이트들

https://api.flutter.dev/flutter/services/EventChannel-class.html

https://www.youtube.com/watch?v=ovbspHZJ9b0&t=958s

https://www.kodeco.com/20518849-an-in-depth-dive-into-streaming-data-across-platform-channels-on-flutter

https://seosh817.tistory.com/301

https://uxicode.tistory.com/entry/스트림-stream-이란