Method Channel là cơ chế giao tiếp hai chiều giữa mã Dart và phía gốc của iOS và Android trong Flutter. Theo Flutter Documentation, 2026, Method Channel đảm bảo truyền các thông điệp đã được định kiểu giữa Dart và nền tảng chủ. Nếu không có cơ chế này, không thể truy cập vào khả năng phần cứng của thiết bị, SDK gốc và các lời gọi hệ thống từ mã ứng dụng.
Những điểm chính
Method Channel là thành phần trung tâm của lớp nền tảng Flutter, qua đó các isolate Dart trao đổi thông điệp với ứng dụng chủ trên iOS hoặc Android. Nhiệm vụ chính của kênh là che giấu sự khác biệt trong giao thức truyền dữ liệu giữa hai nền tảng và cung cấp API thống nhất cho nhà phát triển.
Khi một ứng dụng Flutter cần truy cập vào camera, Bluetooth, cảm biến hoặc bất kỳ API gốc nào khác, việc gọi trực tiếp từ Dart là không thể. Flutter chạy trong một engine được xây dựng trên C++ và không có quyền truy cập vào các framework UIKit hoặc Android SDK. Method Channel giải quyết vấn đề này bằng cách tạo một cầu nối giữa thế giới Dart và thế giới mã gốc.
Theo Google I/O 2024, hơn 80% ứng dụng Flutter trong sản xuất sử dụng ít nhất một Method Channel để tích hợp với các dịch vụ nền tảng. Điều này khẳng định vai trò quan trọng của kênh trong kiến trúc các dự án hiện đại.
Đối với nhà phát triển, Method Channel trông giống như một lời gọi hàm bất đồng bộ thông thường. Bên trong, quá trình tuần tự hóa thông điệp, truyền nó qua bộ đệm engine và thực thi mã gốc trên luồng chính của nền tảng diễn ra.
Tương tác qua Method Channel bắt đầu khi phía Dart gửi một thông điệp chứa tên phương thức và đối số. Flutter Engine nhận thông điệp này, chuyển đổi nó sang định dạng tiêu chuẩn StandardMethodCodec và chuyển tiếp sang phía gốc qua BinaryMessenger.
Phía gốc chứa một trình xử lý — MethodCallHandler, nhận lời gọi đã được giải tuần tự hóa và thực thi logic tương ứng. Kết quả được trả về Dart dưới dạng Response, chứa kết quả thành công hoặc lỗi với mã và thông báo.
Toàn bộ chu trình gọi qua Method Channel có thể được chia thành sáu giai đoạn. Isolate Dart tạo một phiên bản kênh với tên duy nhất để nhận dạng kết nối. Khi gọi invokeMethod, mã nền tảng Dart tuần tự hóa tên phương thức và đối số bằng MethodCodec, chúng chuyển đổi thành bộ đệm nhị phân qua StandardMessageCodec.
Flutter Engine truyền bộ đệm này qua socket sang phía gốc. BinaryMessenger gốc đọc thông điệp, nhận dạng kênh theo tên và gọi trình xử lý đã đăng ký, truyền cho nó một đối tượng FlutterMethodCall với dữ liệu đã phân tích. Trình xử lý thực thi mã cần thiết và trả về kết quả, kết quả đi qua đường tuần tự hóa ngược và đến Dart dưới dạng Future.
Kiến trúc Method Channel bao gồm nhiều thực thể liên kết với nhau, mỗi thực thể chịu trách nhiệm cho giai đoạn truyền dữ liệu riêng. API Dart cung cấp lớp MethodChannel, che giấu khỏi nhà phát triển các chi tiết cấp thấp của tuần tự hóa và định tuyến.
BinaryMessenger là giao diện cấp thấp của Flutter Engine để gửi và nhận thông điệp nhị phân giữa Dart và nền tảng chủ. Mỗi MethodChannel liên kết với một BinaryMessenger cụ thể cung cấp định tuyến theo tên kênh. Phía Dart sử dụng lớp BinaryMessenger, trên Android — BinaryMessenger từ gói io.flutter.embedding.engine, trên iOS — giao thức FlutterBinaryMessenger.
MethodCodec là bộ mã hóa chuyển đổi các lời gọi phương thức và giá trị trả về thành định dạng nhị phân. Flutter đi kèm với hai triển khai tích hợp: StandardMethodCodec (mặc định) và JSONMethodCodec (cho chuỗi JSON). StandardMethodCodec sử dụng bên trong StandardMessageCodec, tuần tự hóa dữ liệu với hỗ trợ tất cả các kiểu cơ bản của Dart.
StandardMessageCodec hỗ trợ một tập hợp hạn chế các kiểu dữ liệu để đảm bảo tương thích giữa Dart, Kotlin và Swift. Danh sách bao gồm: null, bool, int, double, String, Uint8List, Int32List, Int64List, Float64List, List và Map với khóa là chuỗi.
Tất cả các kiểu khác — DateTime, đối tượng DTO hoặc lớp tùy chỉnh — phải được chuyển đổi thành một trong các định dạng đã liệt kê. Cách tiếp cận phổ biến nhất là tuần tự hóa các đối tượng phức tạp thành Map với các trường và tái tạo cấu trúc ở phía nhận từ một từ điển trường.
Để truyền dữ liệu nhị phân lớn, như hình ảnh từ camera, Flutter khuyên dùng BasicMessageChannel với Uint8List để tránh sao chép toàn bộ bộ đệm ở mỗi lần gọi qua MethodChannel.
| Kiểu Dart | Kiểu Kotlin | Kiểu Swift |
|---|---|---|
| null | null | nil |
| bool | Boolean | NSNumber |
| int | Int | NSNumber |
| double | Double | NSNumber |
| String | String | NSString |
| Uint8List | ByteArray | FlutterStandardTypedData |
| List | List | Array |
| Map | HashMap | Dictionary |
Việc thiết lập Method Channel ở phía Android được thực hiện trong một lớp triển khai FlutterPlugin, hoặc trực tiếp trong MainActivity. Cách tiếp cận đầu tiên được khuyến nghị vì nó cung cấp quản lý vòng đời plugin phù hợp và tương thích với các kịch bản add-to-app.
Sau khi tạo một phiên bản kênh với cùng tên như ở phía Dart, cần đăng ký MethodCallHandler qua setMethodCallHandler. Bên trong trình xử lý, nhà phát triển kiểm tra tên phương thức đến bằng when và trả về kết quả qua result.success hoặc lỗi qua result.error với mã và thông báo.
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()
}
}
}
}
Trong ví dụ này, kênh tên samples.flutter.dev/battery xử lý lời gọi getBatteryLevel, lấy mức pin qua Android BatteryManager và trả về cho mã Dart. Tên kênh phải khớp ở cả hai phía, nếu không thông điệp sẽ không đến được trình xử lý.
Đối với mã sản xuất, nên tách logic Method Channel vào một lớp riêng triển khai FlutterPlugin. Điều này cho phép tái sử dụng plugin giữa các dự án và đảm bảo dọn dẹp tài nguyên chính xác khi gọi onDetachedFromEngine. Plugin được đăng ký qua registerWith và có thể được kiểm thử độc lập với Activity.
Method Channel trên iOS được thiết lập trong một lớp triển khai giao thức FlutterPlugin, hoặc trong AppDelegate. Cách tiếp cận khuyến nghị là tạo một lớp plugin riêng biệt đăng ký qua FlutterPluginRegistrar và được quản lý bởi Flutter Engine.
Phía Dart gửi một lời gọi, và trình xử lý gốc nhận một đối tượng FlutterMethodCall với tên phương thức và đối số. Nhà phát triển xác định phương thức được gọi qua switch trên call.method và trả về kết quả qua closure result. Để truy cập API iOS, UIKit và các framework hệ thống khác được sử dụng.
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)
}
}
}
Cách tiếp cận FlutterPlugin đảm bảo đăng ký và hủy kích hoạt plugin chính xác khi Flutter Engine bị phá hủy. Trong trình xử lý Swift, switch trên call.method được sử dụng, mỗi trường hợp trả về kết quả qua closure result. Các đối số có thể truy cập qua call.arguments với việc ép kiểu sang kiểu thích hợp.
Khi làm việc với Method Channel, điều quan trọng là tuân theo một số quy tắc chính để đảm bảo hiệu suất và độ ổn định của ứng dụng. Khuyến nghị chính là giảm thiểu số lượng và khối lượng dữ liệu truyền, đặc biệt trong các lời gọi trong vòng lặp hoạt ảnh hoặc với tần suất cao.
Phía gốc luôn phải xử lý ngoại lệ và trả về lỗi qua result.error với thông báo dễ đọc. Phía Dart, mỗi lời gọi invokeMethod nên được bọc trong try-catch để bắt PlatformException. Bỏ qua lỗi có thể dẫn đến sập ứng dụng bất ngờ mà không có lý do rõ ràng.
Theo mặc định, Method Channel thực thi mã gốc trên luồng chính của nền tảng. Nếu trình xử lý thực hiện một thao tác nặng, cần chuyển việc thực thi sang luồng nền bằng Kotlin Coroutines trên Android hoặc Grand Central Dispatch trên iOS. Kết quả chỉ nên được trả về qua result sau khi hoàn thành công việc trên luồng chính.
Chọn tên duy nhất cho các kênh bằng ký hiệu tên miền đảo ngược — ví dụ: com.example.app/feature. Tên ngắn có thể xung đột với các plugin khác. Flutter đăng ký kênh toàn cục, vì vậy tên giống hệt nhau trong các plugin khác nhau dẫn đến ghi đè trình xử lý và lời gọi hỏng.
Các câu hỏi thường gặp
MethodChannel được thiết kế để gọi các phương thức theo mẫu yêu cầu-phản hồi với mã hóa qua MethodCodec. BasicMessageChannel gửi các thông điệp tùy ý mà không có định dạng phương thức và đối số, thuận tiện cho dữ liệu luồng và sự kiện từ nền tảng.
Trực tiếp — không. StandardMessageCodec chỉ hỗ trợ các kiểu cơ bản: kiểu nguyên thủy, String, Uint8List, List và Map. Các đối tượng tùy chỉnh phải được tuần tự hóa thủ công thành Map trước khi gửi và tái tạo ở phía nhận từ từ điển trường.
Phía gốc, sử dụng result.error với mã lỗi và thông báo. Phía Dart, bọc invokeMethod trong try-catch và bắt PlatformException. Nếu phương thức chưa được triển khai trên nền tảng, trả về result.notImplemented.
Mỗi lời gọi thực hiện tuần tự hóa và sao chép dữ liệu giữa các isolate và nền tảng. Đối với các lời gọi không thường xuyên, chi phí là không đáng kể. Khi truyền megabyte dữ liệu mỗi khung hình, có thể xảy ra độ trễ và giảm FPS. Đối với dữ liệu luồng, hãy sử dụng view nền tảng hoặc đối tượng kết xuất kết cấu.
Sử dụng EventChannel — nó được thiết kế để truyền luồng sự kiện từ phía gốc sang Dart. Nền tảng bắt đầu gửi qua EventSink, và Dart đăng ký luồng bằng receiveBroadcastStream. Method Channel không phù hợp cho kịch bản này.
Tổng kết
Chúng tôi sẽ phát triển ứng dụng di động chìa khóa trao tay
IT Sectr tạo các ứng dụng iOS và Android cho các công ty khởi nghiệp và doanh nghiệp từ năm 2017. Chúng tôi sẽ tư vấn và đề xuất giải pháp tốt nhất cho bạn.