Ang Method Channel ay isang mekanismo ng dalawang-daan na komunikasyon sa pagitan ng Dart code at ng native na bahagi ng iOS at Android sa Flutter. Ayon sa Flutter Documentation, 2026, ang Method Channel ay nagbibigay ng paghahatid ng mga naka-type na mensahe sa pagitan ng Dart at ng host platform. Kung wala ang mekanismong ito, imposibleng ma-access ang mga kakayahan ng hardware ng device, native SDK, at mga system call mula sa code ng application.
Mga pangunahing punto
Method Channel ay ang sentral na bahagi ng platform layer ng Flutter kung saan ang mga Dart isolate ay nagpapalitan ng mga mensahe sa host application sa iOS o Android. Ang pangunahing gawain ng channel ay itago ang mga pagkakaiba sa mga protocol ng paghahatid ng data sa pagitan ng dalawang platform at magbigay ng nag-iisang API para sa developer.
Kapag ang isang Flutter application ay nangangailangan ng access sa camera, Bluetooth, sensor, o anumang iba pang native API, ang direktang tawag mula sa Dart ay imposible. Ang Flutter ay tumatakbo sa isang engine sa C++ at walang access sa UIKit o Android SDK frameworks. Nilulutas ng Method Channel ang problemang ito sa pamamagitan ng paggawa ng tulay sa pagitan ng mundo ng Dart at ng mundo ng native code.
Ayon sa Google I/O 2024, higit sa 80% ng Flutter application sa produksyon ay gumagamit ng hindi bababa sa isang Method Channel para sa pagsasama sa mga serbisyo ng platform. Kinukumpirma nito ang kritikal na papel ng channel sa arkitektura ng mga modernong proyekto.
Para sa developer, ang Method Channel ay mukhang isang tawag sa isang ordinaryong asynchronous function. Sa likod ng mga eksena, nangyayari ang serialisasyon ng mensahe, paghahatid nito sa pamamagitan ng engine buffer, at pagpapatupad ng native code sa pangunahing thread ng platform.
Interaksyon sa pamamagitan ng Method Channel ay nagsisimula kapag ang Dart side ay nagpadala ng isang mensahe na naglalaman ng pangalan ng pamamaraan at mga argumento. Tinatanggap ng Flutter Engine ang mensaheng ito, ginagawang standard na format na StandardMethodCodec, at ipinapadala ito sa native side sa pamamagitan ng BinaryMessenger.
Ang native side ay naglalaman ng isang handler — MethodCallHandler, na tumatanggap ng deserialized na tawag at isinasagawa ang kaukulang lohika. Ang resulta ay ibinabalik sa Dart sa anyo ng Response na naglalaman ng alinman sa matagumpay na resulta o isang error na may code at mensahe.
Ang buong siklo ng tawag sa pamamagitan ng Method Channel ay maaaring hatiin sa anim na yugto. Ang Dart isolate ay gumagawa ng instance ng channel na may natatanging pangalan para sa pagkakakilanlan ng koneksyon. Kapag tumatawag ng invokeMethod, ang Dart platform code ay nagse-serialize ng pangalan ng pamamaraan at mga argumento gamit ang MethodCodec, na ginagawang binary buffer ang mga ito sa pamamagitan ng StandardMessageCodec.
Ipinapadala ng Flutter Engine ang buffer na ito sa pamamagitan ng socket sa native side. Binabasa ng native BinaryMessenger ang mensahe, tinutukoy ang channel sa pamamagitan ng pangalan, at tinatawagan ang naka-rehistrong handler, na ipinapasa dito ang object na FlutterMethodCall na may parsed data. Isinasagawa ng handler ang kinakailangang code at ibinabalik ang resulta, na dumadaan sa reverse serialization path at pumapasok sa Dart bilang Future.
Ang arkitektura ng Method Channel ay binubuo ng ilang magkakaugnay na entity, bawat isa ay responsable para sa sarili nitong yugto ng paghahatid ng data. Ang Dart API ay nagbibigay ng klase na MethodChannel, na itinatago mula sa developer ang mga detalye ng mababang antas ng serialisasyon at routing.
BinaryMessenger ay ang mababang antas na interface ng Flutter Engine para sa pagpapadala at pagtanggap ng mga binary na mensahe sa pagitan ng Dart at ng host platform. Ang bawat MethodChannel ay nakatali sa isang partikular na BinaryMessenger na nagbibigay ng routing ayon sa pangalan ng channel. Sa Dart side ginagamit ang klase na BinaryMessenger, sa Android — BinaryMessenger mula sa package na io.flutter.embedding.engine, sa iOS — ang protocol na FlutterBinaryMessenger.
MethodCodec ay isang encoder na nagko-convert ng mga tawag ng pamamaraan at mga return value sa binary na format. Ang Flutter ay may dalawang built-in na implementasyon: StandardMethodCodec (default) at JSONMethodCodec (para sa JSON strings). Ginagamit ng StandardMethodCodec sa likod ng mga eksena ang StandardMessageCodec, na nagse-serialize ng data na may suporta para sa lahat ng pangunahing uri ng Dart.
StandardMessageCodec ay sumusuporta sa isang limitadong set ng mga uri ng data upang matiyak ang compatibility sa pagitan ng Dart, Kotlin, at Swift. Kasama sa set ang: null, bool, int, double, String, Uint8List, Int32List, Int64List, Float64List, List, at Map na may string keys.
Lahat ng iba pang uri — DateTime, DTO objects, o custom na klase — ay dapat i-convert sa isa sa mga nabanggit na format. Ang pinakakaraniwang approach ay ang pag-serialize ng mga kumplikadong object sa Map na may mga field at ibalik ang istraktura sa receiving side mula sa diksyunaryo ng mga field.
Para sa paglilipat ng malalaking binary data tulad ng mga imahe mula sa camera, inirerekomenda ng Flutter ang paggamit ng BasicMessageChannel na may Uint8List upang maiwasan ang buong pagkopya ng buffer sa bawat tawag sa pamamagitan ng MethodChannel.
| Dart type | Kotlin type | Swift type |
|---|---|---|
| null | null | nil |
| bool | Boolean | NSNumber |
| int | Int | NSNumber |
| double | Double | NSNumber |
| String | String | NSString |
| Uint8List | ByteArray | FlutterStandardTypedData |
| List | List | Array |
| Map | HashMap | Dictionary |
Ang configuration ng Method Channel sa Android side ay ginagawa sa isang klase na nagpapatupad ng FlutterPlugin o direkta sa MainActivity. Ang unang approach ay inirerekomenda dahil tinitiyak nito ang tamang pamamahala ng lifecycle ng plugin at compatibility sa mga add-to-app scenario.
Pagkatapos gumawa ng instance ng channel na may parehong pangalan tulad ng sa Dart side, kailangang mag-rehistro ng MethodCallHandler sa pamamagitan ng setMethodCallHandler. Sa loob ng handler, sinusuri ng developer ang pangalan ng papasok na pamamaraan sa pamamagitan ng when at ibinabalik ang resulta sa pamamagitan ng result.success o error sa pamamagitan ng result.error na may code at mensahe.
package com.example.app
import io.flutter.embedding.android.FlutterActivity
import io.flutter.plugin.common.MethodChannel
class MainActivity : FlutterActivity() {
private val CHANNEL = "samples.flutter.dev/battery"
override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
super.configureFlutterEngine(flutterEngine)
val channel = MethodChannel(flutterEngine.dartExecutor.binaryMessenger, CHANNEL)
channel.setMethodCallHandler { call, result ->
when (call.method) {
"getBatteryLevel" -> {
val batteryLevel = getBatteryLevel()
if (batteryLevel != null) {
result.success(batteryLevel)
} else {
result.error("UNAVAILABLE", "Battery not available", null)
}
}
else -> result.notImplemented()
}
}
}
}
Sa halimbawang ito, ang channel na may pangalang samples.flutter.dev/battery ay nagpoproseso ng tawag na getBatteryLevel, kumukuha ng antas ng baterya sa pamamagitan ng Android BatteryManager, at ibinabalik ito sa Dart code. Ang pangalan ng channel ay dapat pareho sa magkabilang panig, kung hindi, ang mensahe ay hindi makakarating sa handler.
Para sa production code, inirerekomenda na ihiwalay ang lohika ng Method Channel sa isang hiwalay na klase na nagpapatupad ng FlutterPlugin. Ito ay nagbibigay-daan sa muling paggamit ng plugin sa pagitan ng mga proyekto at ginagarantiyahan ang tamang paglilinis ng mga mapagkukunan kapag tinawag ang onDetachedFromEngine. Ang plugin ay nirerehistro sa pamamagitan ng registerWith at maaaring masuri nang hiwalay mula sa Activity.
Ang Method Channel sa iOS ay naka-configure sa isang klase na nagpapatupad ng protocol na FlutterPlugin o sa AppDelegate. Ang inirerekomendang paraan ay ang paggawa ng hiwalay na klase ng plugin na nirerehistro sa pamamagitan ng FlutterPluginRegistrar at pinamamahalaan ng Flutter Engine.
Ang Dart side ay nagpapadala ng tawag, ang native handler ay tumatanggap ng object na FlutterMethodCall na may pangalan ng pamamaraan at mga argumento. Tinutukoy ng developer ang tinawag na pamamaraan sa pamamagitan ng switch sa call.method at ibinabalik ang resulta sa pamamagitan ng closure result. Para sa pag-access sa iOS API, ginagamit ang UIKit at iba pang system frameworks.
import Flutter
import UIKit
public class BatteryPlugin: NSObject, FlutterPlugin {
public static func register(with registrar: FlutterPluginRegistrar) {
let channel = FlutterMethodChannel(
name: "samples.flutter.dev/battery",
binaryMessenger: registrar.messenger())
let instance = BatteryPlugin()
registrar.addMethodCallDelegate(instance, channel: channel)
}
public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) {
switch call.method {
case "getBatteryLevel":
let device = UIDevice.current
device.isBatteryMonitoringEnabled = true
let level = Int(device.batteryLevel * 100)
result(level)
default:
result(FlutterMethodNotImplemented)
}
}
}
Ang FlutterPlugin approach ay ginagarantiyahan ang tamang pagrerehistro at pag-deactivate ng plugin kapag ang Flutter Engine ay nawasak. Sa Swift handler, ginagamit ang switch sa call.method, bawat case ay nagbabalik ng resulta sa pamamagitan ng closure result. Ang mga argumento ay maa-access sa pamamagitan ng call.arguments na may conversion sa naaangkop na uri.
Kapag nagtatrabaho sa Method Channel, mahalagang sundin ang ilang pangunahing patakaran upang matiyak ang pagganap at katatagan ng application. Ang pangunahing rekomendasyon ay bawasan ang bilang at dami ng ipinadalang data, lalo na sa mga tawag sa loob ng mga loop ng animation o may mataas na dalas.
Sa native side, dapat palaging hawakan ang mga exception at ibalik ang error sa pamamagitan ng result.error na may mensaheng nababasa ng tao. Sa Dart side, ang bawat tawag na invokeMethod ay dapat na balot sa try-catch upang mahuli ang PlatformException. Ang pagwawalang-bahala sa mga error ay maaaring humantong sa hindi inaasahang pag-crash ng application nang walang malinaw na dahilan.
Bilang default, ang Method Channel ay nagpapatupad ng native code sa pangunahing thread ng platform. Kung ang handler ay nagsasagawa ng mabigat na operasyon, ang pagpapatupad ay dapat ilipat sa isang background thread gamit ang Kotlin Coroutines sa Android o Grand Central Dispatch sa iOS. Ang pagbabalik ng resulta sa pamamagitan ng result ay dapat mangyari lamang pagkatapos makumpleto ang trabaho sa pangunahing thread.
Pumili ng mga natatanging pangalan para sa mga channel gamit ang reverse domain notation — halimbawa, com.example.app/feature. Ang mga maiikling pangalan ay maaaring sumalungat sa iba pang mga plugin. Nirerehistro ng Flutter ang mga channel nang global, samakatuwid ang magkaparehong pangalan sa iba't ibang plugin ay humahantong sa pag-overwrite ng handler at hindi gumaganang mga tawag.
Mga madalas itanong
MethodChannel ay dinisenyo para sa pagtawag ng mga pamamaraan sa scheme ng tawag-tugon na may encoding sa pamamagitan ng MethodCodec. Ang BasicMessageChannel ay nagpapadala ng mga arbitraryong mensahe n walang format ng pamamaraan at argumento, na maginhawa para sa stream data at mga kaganapan mula sa platform.
Direkta — hindi. Ang StandardMessageCodec ay sumusuporta lamang sa mga pangunahing uri: primitive, String, Uint8List, List, at Map. Ang mga custom na object ay dapat na manual na i-serialize sa Map bago ipadala at ibalik sa receiving side mula sa diksyunaryo ng mga field.
Sa native side gamitin ang result.error na may error code at mensahe. Sa Dart side balutin ang invokeMethod sa try-catch at hulihin ang PlatformException. Kung ang pamamaraan ay hindi ipinatupad sa platform, ibalik ang result.notImplemented.
Ang bawat tawag ay nagsasagawa ng serialisasyon at pagkopya ng data sa pagitan ng mga isolate at platform. Para sa mga bihirang tawag, ang overhead ay hindi gaanong mahalaga. Kapag naglilipat ng megabytes ng data bawat frame, maaaring mangyari ang mga pagkaantala at pagbaba ng FPS. Para sa stream data, gumamit ng mga platform view o texture render object.
Gamitin ang EventChannel — ito ay dinisenyo para sa streaming ng mga kaganapan mula sa native side patungo sa Dart. Ang platform ay nagpapasimula ng pagpapadala sa pamamagitan ng EventSink, at ang Dart ay nag-subscribe sa stream gamit ang receiveBroadcastStream. Ang Method Channel ay hindi angkop para sa sitwasyong ito.
Buod
Gagawa kami ng mobile application na turnkey
Gumagawa ang IT Sectr ng mga iOS at Android application para sa mga startup at negosyo mula noong 2017. Magpapayo kami sa iyo at magmumungkahi ng pinakamahusay na solusyon.