Method Channel — این چیست، ویژگی‌های کار و کاربرد در Flutter

نویسنده: IT Sectr منتشر شده: 2026-06-03 زمان مطالعه: 9 دقیقه

Method Channel مکانیزم ارتباط دوطرفه بین کد Dart و طرف بومی iOS و Android در Flutter است. بر اساس Flutter Documentation, 2026، Method Channel انتقال پیام‌های تایپ‌شده بین Dart و پلتفرم میزبان را فراهم می‌کند. بدون این مکانیزم، دسترسی به قابلیت‌های سخت‌افزاری دستگاه، SDKهای بومی و فراخوانی‌های سیستمی از کد برنامه غیرممکن است.

نکات اصلی

  • Method Channel — مکانیزم اصلی ادغام Flutter با کد بومی iOS و Android.
  • ارتباط دوطرفه — کد Dart می‌تواند متدهای بومی را فراخوانی کند و کد بومی می‌تواند داده‌ها را به Dart برگرداند.
  • ناهمزمانی — همه فراخوانی‌ها به صورت ناهمزمان بدون مسدود کردن رشته اصلی انجام می‌شوند.
  • سریال‌سازی استاندارد — داده‌ها در قالبی سازگار با JSON با پشتیبانی از انواع اولیه، لیست‌ها و دیکشنری‌ها منتقل می‌شوند.
  • BasicMessageChannel — نوع جایگزین کانال برای انتقال جریانی پیام‌های متنی یا باینری.

Method Channel چیست و چرا به آن نیاز داریم

Method Channel — مؤلفه مرکزی لایه پلتفرمی Flutter است که از طریق آن ایزوله‌های Dart با برنامه میزبان در iOS یا Android تبادل پیام می‌کنند. وظیفه اصلی کانال پنهان کردن تفاوت‌های پروتکل‌های انتقال داده بین دو پلتفرم و ارائه یک API واحد برای توسعه‌دهنده است.

وقتی برنامه Flutter به دوربین، بلوتوث، سنسورها یا هر API بومی دیگری نیاز دارد، فراخوانی مستقیم از Dart غیرممکن است. Flutter در موتور مبتنی بر C++ اجرا می‌شود و به فریم‌ورک‌های UIKit یا Android SDK دسترسی ندارد. Method Channel این مشکل را با ایجاد پلی بین دنیای Dart و دنیای کد بومی حل می‌کند.

بر اساس Google I/O 2024، بیش از 80% برنامه‌های Flutter در تولید حداقل از یک Method Channel برای ادغام با سرویس‌های پلتفرمی استفاده می‌کنند. این نقش حیاتی کانال را در معماری پروژه‌های مدرن تأیید می‌کند.

برای توسعه‌دهنده، Method Channel مانند فراخوانی یک تابع ناهمزمان معمولی به نظر می‌رسد. در پشت صحنه، سریال‌سازی پیام، انتقال آن از طریق بافر موتور و اجرای کد بومی روی رشته اصلی پلتفرم انجام می‌شود.

Method Channel چگونه کار می‌کند

تعامل از طریق Method Channel با ارسال پیامی از طرف Dart که شامل نام متد و آرگومان‌ها است آغاز می‌شود. Flutter Engine این پیام را دریافت کرده، آن را به فرمت استاندارد StandardMethodCodec تبدیل کرده و از طریق BinaryMessenger به طرف بومی منتقل می‌کند.

طرف بومی شامل یک handler به نام MethodCallHandler است که فراخوانی Deserialized را دریافت کرده و منطق مربوطه را اجرا می‌کند. نتیجه به صورت Response شامل یا نتیجه موفق یا خطا با کد و پیام به Dart بازگردانده می‌شود.

فرآیند فراخوانی گام به گام

کل چرخه فراخوانی از طریق Method Channel را می‌توان به شش مرحله تقسیم کرد. ایزوله Dart یک نمونه کانال با نام یکتا برای شناسایی اتصال ایجاد می‌کند. هنگام فراخوانی invokeMethod، کد پلتفرمی Dart نام متد و آرگومان‌ها را با MethodCodec سریال‌سازی می‌کند که آنها را از طریق StandardMessageCodec به بافر باینری تبدیل می‌کند.

Flutter Engine این بافر را از طریق سوکت به طرف بومی منتقل می‌کند. BinaryMessenger بومی پیام را می‌خواند، کانال را بر اساس نام شناسایی کرده و handler ثبت‌شده را فراخوانی می‌کند و شیء FlutterMethodCall با داده‌های تجزیه‌شده به آن منتقل می‌کند. Handler کد مورد نظر را اجرا کرده و نتیجه را برمی‌گرداند که مسیر معکوس سریال‌سازی را طی کرده و به صورت Future وارد Dart می‌شود.

معماری Method Channel: اجزای کلیدی

معماری Method Channel از چندین موجودیت مرتبط تشکیل شده است که هر کدام مسئول مرحله خود از انتقال داده هستند. Dart API کلاس MethodChannel را ارائه می‌دهد که جزئیات سطح پایین سریال‌سازی و مسیریابی را از توسعه‌دهنده پنهان می‌کند.

BinaryMessenger

BinaryMessenger — رابط سطح پایین Flutter Engine برای ارسال و دریافت پیام‌های باینری بین Dart و پلتفرم میزبان. هر MethodChannel به یک BinaryMessenger خاص متصل می‌شود که مسیریابی بر اساس نام کانال را تضمین می‌کند. در طرف Dart از کلاس BinaryMessenger، در Android از BinaryMessenger بسته io.flutter.embedding.engine و در iOS از پروتکل FlutterBinaryMessenger استفاده می‌شود.

MethodCodec و MessageCodec

MethodCodec — کدکننده‌ای است که فراخوانی‌های متد و مقادیر بازگشتی را به فرمت باینری تبدیل می‌کند. Flutter با دو پیاده‌سازی داخلی ارائه می‌شود: StandardMethodCodec (پیش‌فرض) و JSONMethodCodec (برای رشته‌های JSON). StandardMethodCodec در پشت صحنه از StandardMessageCodec استفاده می‌کند که داده‌ها را با پشتیبانی از تمام انواع پایه Dart سریال‌سازی می‌کند.

انواع داده و سریال‌سازی در Method Channel

StandardMessageCodec از مجموعه محدودی از انواع داده برای اطمینان از سازگاری بین Dart، Kotlin و Swift پشتیبانی می‌کند. این مجموعه شامل: null، bool، int، double، String، Uint8List، Int32List، Int64List، Float64List، List و Map با کلیدهای رشته‌ای است.

تمام انواع دیگر — DateTime، اشیاء DTO یا کلاس‌های سفارشی — باید به یکی از فرمت‌های ذکر شده تبدیل شوند. رایج‌ترین رویکرد سریال‌سازی اشیاء پیچیده به Map با فیلدها و بازسازی ساختار در طرف گیرنده از دیکشنری فیلدها است.

برای انتقال داده‌های باینری حجیم مانند تصاویر دوربین، Flutter استفاده از BasicMessageChannel با Uint8List را توصیه می‌کند تا از کپی کامل بافر در هر فراخوانی از طریق MethodChannel جلوگیری شود.

نوع Dartنوع Kotlinنوع Swift
nullnullnil
boolBooleanNSNumber
intIntNSNumber
doubleDoubleNSNumber
StringStringNSString
Uint8ListByteArrayFlutterStandardTypedData
ListListArray
MapHashMapDictionary

Method Channel در Android: تنظیمات در Kotlin

تنظیم Method Channel در طرف Android در کلاسی که FlutterPlugin را پیاده‌سازی می‌کند یا مستقیماً در MainActivity انجام می‌شود. رویکرد اول توصیه می‌شود زیرا مدیریت صحیح چرخه حیات پلاگین و سازگاری با سناریوهای add-to-app را تضمین می‌کند.

پس از ایجاد نمونه کانال با همان نام طرف Dart، باید MethodCallHandler را از طریق setMethodCallHandler ثبت کرد. در داخل handler، توسعه‌دهنده نام متد ورودی را از طریق when بررسی کرده و نتیجه را از طریق result.success یا خطا را از طریق result.error با کد و پیام برمی‌گرداند.

kotlin
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()
            }
        }
    }
}

در این مثال، کانال با نام samples.flutter.dev/battery فراخوانی getBatteryLevel را پردازش کرده، سطح باتری را از طریق Android BatteryManager دریافت کرده و به کد Dart برمی‌گرداند. نام کانال باید در هر دو طرف یکسان باشد، در غیر این صورت پیام به handler نمی‌رسد.

ایجاد پلاگین از طریق FlutterPlugin

برای کد تولید، توصیه می‌شود منطق Method Channel را در یک کلاس جداگانه که FlutterPlugin را پیاده‌سازی می‌کند قرار دهید. این امکان استفاده مجدد از پلاگین بین پروژه‌ها را فراهم کرده و پاکسازی صحیح منابع را هنگام فراخوانی onDetachedFromEngine تضمین می‌کند. پلاگین از طریق registerWith ثبت شده و می‌تواند به صورت جداگانه از Activity آزمایش شود.

Method Channel در iOS: تنظیمات در Swift

Method Channel در iOS در کلاسی که پروتکل FlutterPlugin را پیاده‌سازی می‌کند یا در AppDelegate تنظیم می‌شود. روش توصیه‌شده ایجاد یک کلاس پلاگین جداگانه است که از طریق FlutterPluginRegistrar ثبت شده و توسط Flutter Engine مدیریت می‌شود.

طرف Dart فراخوانی را ارسال می‌کند، handler بومی شیء FlutterMethodCall را با نام متد و آرگومان‌ها دریافت می‌کند. توسعه‌دهنده متد فراخوانی‌شده را از طریق switch بر اساس call.method تعیین کرده و نتیجه را از طریق closure result برمی‌گرداند. برای دسترسی به API iOS از UIKit و سایر فریم‌ورک‌های سیستمی استفاده می‌شود.

swift
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)
        }
    }
}

رویکرد FlutterPlugin ثبت صحیح و غیرفعال‌سازی پلاگین را هنگام نابودی Flutter Engine تضمین می‌کند. در handler Swift از switch بر اساس call.method استفاده می‌شود، هر case نتیجه را از طریق closure result برمی‌گرداند. آرگومان‌ها از طریق call.arguments با تبدیل به نوع مربوطه در دسترس هستند.

بهترین روش‌های Method Channel و خطاهای رایج

هنگام کار با Method Channel رعایت چند قانون کلیدی برای تضمین عملکرد و پایداری برنامه مهم است. توصیه اصلی به حداقل رساندن تعداد و حجم داده‌های منتقل‌شده، به‌ویژه در فراخوانی‌های درون حلقه‌های انیمیشن یا با فرکانس بالا است.

مدیریت خطا

در طرف بومی همیشه باید استثناها را مدیریت کرده و خطا را از طریق result.error با پیام قابل خواندن برای انسان برگردانید. در طرف Dart هر فراخوانی invokeMethod باید برای catch PlatformException در try-catch پیچیده شود. نادیده گرفتن خطاها می‌تواند منجر به crash غیرمنتظره برنامه بدون دلیل مشخص شود.

ایزوله‌سازی رشته‌ها

به طور پیش‌فرض، Method Channel کد بومی را روی رشته اصلی پلتفرم اجرا می‌کند. اگر handler عملیات سنگینی انجام می‌دهد، باید اجرا را با Kotlin Coroutines در Android یا Grand Central Dispatch در iOS به رشته پس‌زمینه منتقل کرد. نتیجه از طریق result فقط پس از اتمام کار روی رشته اصلی برگردانده شود.

نام‌گذاری کانال‌ها

نام‌های یکتا برای کانال‌ها با استفاده از نمادگذاری دامنه معکوس انتخاب کنید — به عنوان مثال com.example.app/feature. نام‌های کوتاه ممکن است با سایر پلاگین‌ها تداخل داشته باشند. Flutter کانال‌ها را به صورت سراسری ثبت می‌کند، بنابراین نام‌های یکسان در پلاگین‌های مختلف منجر به بازنویسی handler و عدم کارکرد فراخوانی‌ها می‌شود.

سوالات متداول

تفاوت بین MethodChannel و BasicMessageChannel چیست؟

MethodChannel برای فراخوانی متدها در طرح فراخوانی-پاسخ با کدگذاری از طریق MethodCodec طراحی شده است. BasicMessageChannel پیام‌های دلخواه را بدون فرمت متد و آرگومان منتقل می‌کند که برای داده‌های جریانی و رویدادهای پلتفرم مناسب است.

آیا می‌توان اشیاء سفارشی را از طریق Method Channel منتقل کرد؟

مستقیماً — خیر. StandardMessageCodec فقط از انواع پایه پشتیبانی می‌کند: انواع اولیه، String، Uint8List، List و Map. اشیاء سفارشی باید قبل از ارسال به صورت دستی به Map سریال‌سازی شده و در طرف گیرنده از دیکشنری فیلدها بازسازی شوند.

چگونه خطاها را هنگام فراخوانی Method Channel مدیریت کنیم؟

در طرف بومی از result.error با کد خطا و پیام استفاده کنید. در طرف Dart invokeMethod را در try-catch بپیچید و PlatformException را بگیرید. اگر متد در پلتفرم پیاده‌سازی نشده است، result.notImplemented را برگردانید.

آیا Method Channel بر عملکرد تأثیر می‌گذارد؟

هر فراخوانی سریال‌سازی و کپی داده‌ها را بین ایزوله‌ها و پلتفرم‌ها انجام می‌دهد. برای فراخوانی‌های نادر، سربار ناچیز است. هنگام انتقال مگابایت داده در هر فریم، تأخیر و کاهش FPS ممکن است رخ دهد. برای داده‌های جریانی از viewهای پلتفرمی یا اشیاء رندر بافت‌دار استفاده کنید.

چگونه یک رویداد را از پلتفرم به Dart بدون فراخوانی از Dart منتقل کنیم؟

از EventChannel استفاده کنید — این کانال برای جریان رویدادها از طرف بومی به Dart طراحی شده است. پلتفرم ارسال را از طریق EventSink آغاز می‌کند و Dart با receiveBroadcastStream در جریان مشترک می‌شود. Method Channel برای این سناریو مناسب نیست.

خلاصه

  • Method Channel — مکانیزم اصلی ادغام پلتفرمی Flutter برای ارتباط دوطرفه ناهمزمان بین Dart و کد بومی iOS و Android.
  • معماری شامل BinaryMessenger، MethodCodec و MethodCallHandler است که با هم سریال‌سازی، مسیریابی و اجرای فراخوانی‌ها را تضمین می‌کنند.
  • انواع داده به مجموعه StandardMessageCodec محدود می‌شوند: انواع اولیه، رشته‌ها، لیست‌ها، دیکشنری‌ها و بافرهای تایپ‌شده.
  • تنظیمات در Android از طریق FlutterPlugin با MethodChannel در Kotlin و در iOS از طریق FlutterPlugin با FlutterMethodChannel در Swift انجام می‌شود.
  • عملکرد نیازمند به حداقل رساندن حجم داده‌های منتقل‌شده و استفاده از EventChannel برای رویدادهای جریانی است.
  • خطاها از طریق result.error در پلتفرم و catch PlatformException در طرف Dart مدیریت می‌شوند.
  • معماری پلاگین با FlutterPlugin بر کد مستقیم در Activity ترجیح داده می‌شود زیرا مدیریت صحیح چرخه حیات را تضمین می‌کند.

ما یک اپلیکیشن موبایل به صورت کلید در دست توسعه خواهیم داد

IT Sectr از سال 2017 برنامه‌های iOS و Android را برای استارتاپ‌ها و کسب‌وکارها ایجاد می‌کند. ما به شما مشاوره می‌دهیم و بهترین راه‌حل را پیشنهاد خواهیم کرد.

بحث درباره پروژه