Flutter를 시작할때 가장 어렵게 느껴진게 MethodChannel 이었습니다.
오늘은 MethodChannel이 어렵지 않음을 최대한 설명하고자 합니다.
그리고 flutter는 cross platform이지만 장점이 pub.dev를 통해서 platform 기능을 이용하기 위한 library 제공받을 수 있는것이지만 또한 한계가 있음을 자주 느낍니다.
내가 원하는 기능이 없거나 예상대로 동작을 안하는 경우들이 간혹 있기 때문입니다.
그래서 이런 경우 Android에 익숙하신 개발자분들은 Platform에 곧바로 코드를 만들어 MethodChannel을 통해서 사용하는게 유리할 경우가 있습니다.
Flutter는 Platform안에서 동작
Flutter는 근본적으로는 Platform안에서 동작하는 것이기 때문에 지금 다루는 Android는 아래 그림과 같이 MainActivity부터 시작되고 있습니다.
즉, Flutter로 개발을 하지만 실제는 Android Platform의 App Program의 기본 단위인 Activity 기반으로 동작하고 있는 것입니다.
MethodChannel을 알아보면 플랫폼 별 코드 작성을 글에 있는 아키텍처 그림을 가장 먼저 보게되는데 전 잘 와닿지 않더라구요.
그래서 다시 그려봤습니다.
아래 그림에서 핵심은 binary message입니다.
실제 Platform API를 통해서 동작해야 하는 것은 Activity에서 동작하고 Flutter View는 Activity에 존재하는 code를 호출하되 byte로 만들어진 message를 통해서 interfacing하는 것입니다.
Flutter to Platform
Channel 이름 정하기
“com.kowanas.idea_market/main” 으로 이름을 정하고 activity와 flutter 쪽에서도 이 이름을 통하여 method call을 하도록 합니다.
사용방법은 MethodChannel(“com.kowanas.idea_market/main”)으로 Channel이름을 인자로 instance를 생성합니다.
Method 호출하기
앞서 만들었던 MethodChannel instance를 platform이라는 이름으로 정의하였습니다.
platform.invokeMethod를 사용하되 Method name을 첫번째 인자로 넣어줍니다.
위 예는 “request_permission”이 Method name입니다.
Android쪽에서는 다음 예시와 같이 call.method로 참조하면 됩니다.
if (call.method == "request_permission")
Argument 전달하기
platform.invokeMethod의 두번째 인자로 전달합니다.
HashMap을 사용하였고 내부적으로 Byte로 변환하여 encoding/decoding을 합니다.
그럼 Android쪽에서는 call.argument(key
) 를 이용하여 값을 읽어옵니다.
결과 Return하기
result.succss 또는 result.error를 사용할 수가 있습니다.
아래는 Result Interface Code입니다.
저는 result.success로 permission이 승인되었으면 true, 아니면 false를 인자로 return하도록 하였으며 인자 타입은 다양한 Object를 사용하시면 됩니다.
Flutter쪽에서 제 코드를 보시면 return await platform.invokeMethod(.. 를 하는데 있어 await를 사용하고 있습니다.
invokeMethod 결과를 받을때까지 대기했다가 처리하기 위함입니다.
하지만, 경우에 따라서 곧바로 결과를 받을 수 없고 async로 결과를 받아야 하는 경우가 있습니다.
이 경우는 EventChannel을 사용하게 되는데 이 내용은 내용이 길어지게 되니 다른 Chapter에서 설명하도록 하겠습니다.
마치며
간단하지만 조금만 저의 예시로 올린 코드를 살펴 보면 Method Channel 사용이 어렵지 않음을 알 수 있습니다.
즉, Activity에 만들어진 Code를 호출하기 위해서 MethodChannel의 method와 argument로 구성이 되는 wrapper를 만들어서 같은 이름과 같은 key로 Android Platform과 Flutter간에 encoding/decoding하면 되는 구조입니다.
위 코드는 Permission 처리를 permission library를 사용할 수도 있겠지만 기존에 이미 코드가 만들어져 있거나 library를 익히는것보다 직접 만들어버리는게 자연스럽다면 부담없이 platform code를 구현하여 MethodChannel을 이용하여 호출하여 사용하는 것이 생산성과 유지보수에 훨씬 유리할 수가 있습니다.
또는 원하는 platform기능에 대한 library가 없는 경우는 MethodChannel을 사용하는 것이 필수겠죠?
제가 Permission을 처리하는 code는 github에 idea_market c41128 을 참조하시면 됩니다.
다음 Chapter를 Permission 처리를 구현한걸 정리할지 camera 사용을 정리할지 고민중입니다.
그런데 생각해보면 Flutter만 가지고 앱의 모든 기능을 완성하지 못하는 것은 결국 Android Platform Code를 구현하는 스킬을 배워야 하니 Flutter의 단점이 될 수도 있습니다.