Method Channel is een mechanisme voor bidirectionele communicatie tussen Dart-code en de native kant van iOS en Android in Flutter. Volgens Flutter Documentation, 2026 zorgt Method Channel voor de overdracht van getypeerde berichten tussen Dart en het hostplatform. Zonder dit mechanisme is het onmogelijk om toegang te krijgen tot de hardwaremogelijkheden van het apparaat, native SDK's en systeemaanroepen vanuit de applicatiecode.
Belangrijkste punten
Method Channel is de centrale component van de platformlaag van Flutter waarmee Dart-isolaten berichten uitwisselen met de hostapplicatie op iOS of Android. De belangrijkste taak van het kanaal is het verbergen van verschillen in gegevensoverdrachtprotocollen tussen de twee platforms en het bieden van een uniforme API voor de ontwikkelaar.
Wanneer een Flutter-applicatie toegang nodig heeft tot de camera, Bluetooth, sensoren of een andere native API, is een directe aanroep vanuit Dart onmogelijk. Flutter draait in een engine op C++ en heeft geen toegang tot UIKit- of Android SDK-frameworks. Method Channel lost dit probleem op door een brug te slaan tussen de wereld van Dart en de wereld van native code.
Volgens Google I/O 2024 gebruikt meer dan 80% van de Flutter-applicaties in productie ten minste één Method Channel voor integratie met platformdiensten. Dit bevestigt de kritieke rol van het kanaal in de architectuur van moderne projecten.
Voor de ontwikkelaar ziet Method Channel eruit als een aanroep van een gewone asynchrone functie. Onder de motorkap vindt serialisatie van het bericht plaats, overdracht via de enginebuffer en uitvoering van native code op de hoofdthread van het platform.
Interactie via Method Channel begint wanneer de Dart-kant een bericht verzendt met de naam van de methode en argumenten. Flutter Engine ontvangt dit bericht, converteert het naar het standaardformaat StandardMethodCodec en geeft het door aan de native kant via BinaryMessenger.
De native kant bevat een handler — MethodCallHandler, die de gedeserialiseerde aanroep ontvangt en de bijbehorende logica uitvoert. Het resultaat wordt teruggegeven aan Dart in de vorm van een Response die ofwel een succesvol resultaat ofwel een fout met code en bericht bevat.
De volledige aanroepcyclus via Method Channel kan worden verdeeld in zes fasen. Het Dart-isolaat maakt een kanaalinstantie met een unieke naam voor identificatie van de verbinding. Bij aanroep van invokeMethod serialiseert de Dart-platformcode de methodenaam en argumenten met MethodCodec, die ze via StandardMessageCodec omzet in een binaire buffer.
Flutter Engine geeft deze buffer via een socket door aan de native kant. Native BinaryMessenger leest het bericht, identificeert het kanaal op naam en roept de geregistreerde handler aan, waarbij het object FlutterMethodCall met geparseerde gegevens wordt doorgegeven. De handler voert de benodigde code uit en retourneert het resultaat, dat de omgekeerde serialisatieroute doorloopt en in Dart binnenkomt als Future.
De architectuur van Method Channel bestaat uit verschillende onderling verbonden entiteiten, die elk verantwoordelijk zijn voor hun eigen fase van gegevensoverdracht. Dart API biedt de klasse MethodChannel, die de ontwikkelaar de details van serialisatie en routering op laag niveau verbergt.
BinaryMessenger is de low-level interface van Flutter Engine voor het verzenden en ontvangen van binaire berichten tussen Dart en het hostplatform. Elke MethodChannel is gekoppeld aan een specifieke BinaryMessenger die routering op kanaalnaam mogelijk maakt. Aan de Dart-kant wordt de klasse BinaryMessenger gebruikt, op Android — BinaryMessenger uit het pakket io.flutter.embedding.engine, op iOS — het protocol FlutterBinaryMessenger.
MethodCodec is een encoder die methodeaanroepen en retourwaarden omzet in binair formaat. Flutter wordt geleverd met twee ingebouwde implementaties: StandardMethodCodec (standaard) en JSONMethodCodec (voor JSON-teksten). StandardMethodCodec gebruikt onder de motorkap StandardMessageCodec, die gegevens serialiseert met ondersteuning voor alle basis Dart-typen.
StandardMessageCodec ondersteunt een beperkte set gegevenstypen om compatibiliteit tussen Dart, Kotlin en Swift te garanderen. De set omvat: null, bool, int, double, String, Uint8List, Int32List, Int64List, Float64List, List en Map met string-sleutels.
Alle andere typen — DateTime, DTO-objecten of aangepaste klassen — moeten worden geconverteerd naar een van de genoemde formaten. De meest voorkomende aanpak is het serialiseren van complexe objecten naar Map met velden en het herstellen van de structuur aan de ontvangende kant uit het veldenwoordenboek.
Voor het verzenden van grote binaire gegevens zoals camerabeelden raadt Flutter het gebruik van BasicMessageChannel met Uint8List aan om volledige bufferkopiëring bij elke aanroep via MethodChannel te voorkomen.
| 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 |
Configuratie van Method Channel aan de Android-kant gebeurt in een klasse die FlutterPlugin implementeert of direct in MainActivity. De eerste benadering heeft de voorkeur omdat deze zorgt voor correct beheer van de levenscyclus van de plugin en compatibiliteit met add-to-app-scenario's.
Na het maken van een kanaalinstantie met dezelfde naam als aan de Dart-kant, moet MethodCallHandler worden geregistreerd via setMethodCallHandler. Binnen de handler controleert de ontwikkelaar de naam van de inkomende methode via when en retourneert het resultaat via result.success of een fout via result.error met code en bericht.
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()
}
}
}
}
In dit voorbeeld verwerkt het kanaal met de naam samples.flutter.dev/battery de aanroep getBatteryLevel, haalt het batterijniveau op via Android BatteryManager en retourneert het naar de Dart-code. De kanaalnaam moet aan beide kanten hetzelfde zijn, anders bereikt het bericht de handler niet.
Voor productiecode wordt aanbevolen de Method Channel-logica in een aparte klasse te plaatsen die FlutterPlugin implementeert. Dit maakt hergebruik van de plugin tussen projecten mogelijk en garandeert correcte opschoning van bronnen bij aanroep van onDetachedFromEngine. De plugin wordt geregistreerd via registerWith en kan geïsoleerd van Activity worden getest.
Method Channel op iOS wordt geconfigureerd in een klasse die het protocol FlutterPlugin implementeert of in AppDelegate. De aanbevolen manier is het maken van een aparte plugin-klasse die wordt geregistreerd via FlutterPluginRegistrar en wordt beheerd door Flutter Engine.
De Dart-kant verzendt een aanroep, de native handler ontvangt het object FlutterMethodCall met de methodenaam en argumenten. De ontwikkelaar bepaalt de aangeroepen methode via switch op call.method en retourneert het resultaat via de closure result. Voor toegang tot de iOS API worden UIKit en andere systeemframeworks gebruikt.
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)
}
}
}
De FlutterPlugin-benadering garandeert correcte registratie en deactivering van de plugin bij vernietiging van Flutter Engine. In de Swift-handler wordt switch gebruikt op call.method, elke case retourneert het resultaat via de closure result. Argumenten zijn toegankelijk via call.arguments met conversie naar het juiste type.
Bij het werken met Method Channel is het belangrijk om een aantal belangrijke regels te volgen voor de prestaties en stabiliteit van de applicatie. De belangrijkste aanbeveling is het minimaliseren van het aantal en volume van verzonden gegevens, vooral bij aanroepen in animatielussen of met hoge frequentie.
Aan de native kant moeten altijd uitzonderingen worden afgehandeld en moet de fout worden geretourneerd via result.error met een leesbaar bericht. Aan de Dart-kant moet elke invokeMethod-aanroep worden omgeven door try-catch om PlatformException op te vangen. Het negeren van fouten kan leiden tot een onverwachte crash van de applicatie zonder duidelijke reden.
Standaard voert Method Channel native code uit op de hoofdthread van het platform. Als de handler een zware bewerking uitvoert, moet de uitvoering worden verplaatst naar een achtergrondthread met behulp van Kotlin Coroutines op Android of Grand Central Dispatch op iOS. Het retourneren van het resultaat via result mag alleen plaatsvinden nadat het werk op de hoofdthread is voltooid.
Kies unieke namen voor kanalen met behulp van omgekeerde domain notatie — bijvoorbeeld com.example.app/feature. Korte namen kunnen conflicteren met andere plugins. Flutter registreert kanalen wereldwijd, dus identieke namen in verschillende plugins leiden tot overschrijven van de handler en niet-werkende aanroepen.
Veelgestelde vragen
MethodChannel is bedoeld voor het aanroepen van methoden in een aanroep-antwoord schema met codering via MethodCodec. BasicMessageChannel verzendt willekeurige berichten zonder methode- en argumentformaat, wat handig is voor streamgegevens en gebeurtenissen van het platform.
Direct — nee. StandardMessageCodec ondersteunt alleen basistypen: primitieven, String, Uint8List, List en Map. Aangepaste objecten moeten handmatig worden geserialiseerd naar Map vóór verzending en worden hersteld aan de ontvangende kant uit het veldenwoordenboek.
Aan de native kant gebruik result.error met foutcode en bericht. Aan de Dart-kant omvat invokeMethod in try-catch en vang PlatformException. Als de methode niet is geïmplementeerd op het platform, retourneer result.notImplemented.
Elke aanroep voert serialisatie en gegevenskopiëring uit tussen isolaten en platforms. Voor zeldzame aanroepen is de overhead verwaarloosbaar. Bij het verzenden van megabytes aan gegevens per frame kunnen vertragingen en FPS-daling optreden. Gebruik voor streamgegevens platformweergaven of getextureerde renderobjecten.
Gebruik EventChannel — dit is bedoeld voor het streamen van gebeurtenissen van de native kant naar Dart. Het platform initieert verzending via EventSink en Dart abonneert zich op de stream via receiveBroadcastStream. Method Channel is niet geschikt voor dit scenario.
Samenvatting
We ontwikkelen een mobiele applicatie turnkey
IT Sectr creëert sinds 2017 iOS- en Android-applicaties voor startups en bedrijven. We adviseren u en stellen de beste oplossing voor.