Yazılar4 dk okuma
Flutter Method Channel: A Chain of Responsibility Approach
Flutter uygulamalarında Dart koduyla yerel platformlar (Android/iOS) arasında iletişim kurarken, gelen Method Channel çağrılarının farklı senaryolar için ele alınması gerekir.

Herkese merhaba!
Sabah uyanıyorsunuz, mutfağa gidiyorsunuz ve kahve yapmak istiyorsunuz. Ama kahve makinesi bozulmuş. Ne yaparsınız? Önce kahve makinesini kontrol edersiniz. Çalışmıyorsa, kettle’a yönelirsiniz. O da mı bozuk? Bu sefer, filtre kahve düşünürsünüz. En sonunda, kahveyi dışarıdan almaya karar verirsiniz. İşte bu, hayatımızdaki küçük bir Chain of Responsibility (Sorumluluk Zinciri) örneği!
Her bir adım, zincirin bir halkasıdır ve talep, bu zincirdeki halkalar arasında dolaşır. Eğer bir adımda başarı sağlanırsa, işlem orada durur. Eğer başarı sağlanamazsa, istek sıradaki halkaya geçer.

Peki, Flutter’da Method Channel ile bunun ne ilgisi bar?
Aslında, oldukça fazla! Method Channel ile Flutter’dan Android ya da iOS’a bir talep gönderdiğinizde, bu talep doğrudan işlenecek bir yer arar. Eğer istek bir yönteme uymuyorsa, sıradaki işleyiciye geçer. İşte bu noktada Chain of Responsibility Pattern devreye girer.
Flutter uygulamalarında Dart koduyla yerel platformlar (Android/iOS) arasında iletişim kurarken, gelen Method Channel çağrılarının farklı senaryolar için ele alınması gerekir. Bu işlemi bir zincire dönüştürdüğümüzde, her bir istek bir sonraki halkaya geçirilir. Her halka, kahve makinesine, kettle’a ya da filtre kahveye benzer şekilde bir görevi üstlenir. Her istek bir zincir boyunca dolaşır ve doğru işleyici tarafından ele alınır.
Method Channel Nedir?
MethodChannel, Flutter uygulamasında Dart kodunu Android (Kotlin/Java) veya iOS (Swift/Objective-C) koduyla entegre etmek için kullanılır. Bir Method Channel, Dart tarafından bir çağrıyı tetikler ve native platformda karşılık gelen bir işlemi gerçekleştirir.
Hazırsanız, şimdi Android ve iOS kodlarımızı yazmaya başlayalım ve bu yapıyı hayata geçirelim!
IAction
IAction arayüzü, native işlevlerin modüler bir şekilde yönetilmesini sağlar. Her bir işlev, bir sınıf ile temsil edilir ve belirli bir eylem gerçekleştirilir. Bu tasarım deseni, açık kapalı prensibini (Open/Closed Principle) destekler.
interface IAction {
fun isSatisfied(methodName: String): Boolean
fun execute(mainActivity: MainActivity, call: MethodCall, result: MethodChannel.Result)
}
protocol IAction {
func isSatisfied(methodName: String) -> Bool
func execute(controller: FlutterViewController, call: FlutterMethodCall, result: FlutterResult)
}
- isSatisfied: Bu metod,
MethodChannelüzerinden gelen çağrının hangi işleme uygun olduğunu belirler. - execute: Çağrıyı işleyen ve sonucu Flutter’a geri gönderen metoddur.
Avantajları:
- Eylemler kolayca eklenebilir veya çıkarılabilir.
- Her işlev kendi sınıfında yönetildiği için kodun bakımı kolaydır.
executemetodu içinde her işlev için özelleştirilmiş işlemler tanımlanabilir.
MethodChannelHandler
MethodChannelHandler, bir eylem (action) yöneticisi gibi çalışır. Gelen çağrıları belirli bir eyleme yönlendirir ve modüler yapıyı sağlar.
class MethodChannelHandler(private val actions: List<IAction>) {
fun handle(mainActivity: MainActivity, call: MethodCall, result: MethodChannel.Result) {
for (action in actions) {
if (action.isSatisfied(call.method)) {
action.execute(mainActivity, call, result)
return
}
}
result.notImplemented()
}
}
class MethodChannelHandler {
private var actions: [IAction]
init(actions: [IAction]) {
self.actions = actions
}
func handle(controller: FlutterViewController, call: FlutterMethodCall, result: FlutterResult) {
for action in actions {
if action.isSatisfied(methodName: call.method) {
action.execute(controller: controller, call: call, result: result)
return
}
}
result(FlutterMethodNotImplemented)
}
}
Kullanım Senaryosu
MoveToBackgroundAction
MoveToBackgroundAction sınıfı, uygulamanın arka plana taşınması işlemini yönetir
class MoveToBackgroundAction : IAction {
override fun isSatisfied(methodName: String): Boolean {
return methodName == "moveToBackground"
}
override fun execute(
mainActivity: MainActivity,
call: MethodCall,
result: MethodChannel.Result
) {
mainActivity.moveTaskToBack(true)
result.success(null)
}
}
class MoveToBackgroundAction: IAction {
func isSatisfied(methodName: String) -> Bool {
return methodName == "moveToBackground"
}
func execute(
controller: FlutterViewController,
call: FlutterMethodCall,
result: FlutterResult
) {
exit(0)
result(nil)
}
}
MainActivity ve AppDelegate
MainActivity ve AppDelegate içinde IAction örnekleri tanımlanarak MethodChannelHandler’a parametre olarak aktarılır.
class MainActivity : FlutterActivity() {
private val CHANNEL = "com.example.sample/channel"
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val actions = listOf(
MoveToBackgroundAction(),
GetMicrophonesAction(),
)
val handler = MethodChannelHandler(actions)
// Method Channel for Flutter communication
flutterEngine?.dartExecutor?.binaryMessenger?.let { binaryMessenger ->
MethodChannel(binaryMessenger, CHANNEL).setMethodCallHandler { call, result ->
handler.handle(this, call, result)
}
}
}
}
@main
@objc class AppDelegate: FlutterAppDelegate, PKPushRegistryDelegate {
override func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
let controller : FlutterViewController = window?.rootViewController as! FlutterViewController
let channel = FlutterMethodChannel(name: "com.example.sample/channel", binaryMessenger: controller.binaryMessenger)
let actions = [
MoveToBackgroundAction(),
GetMicrophonesAction(),
]
let handler = MethodChannelHandler(actions: actions)
// Method Channel for Flutter communication
channel.setMethodCallHandler({
[weak self] (call: FlutterMethodCall, result: FlutterResult) -> Void in
handler.handle(controller: controller, call: call, result: result)
})
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
}
}
Avantajları
IAction ve MethodChannelHandler kullanımı, aşağıdaki avantajları sunar:
- Modülerlik: Her bir işlev bağımsız bir sınıfta tanımlanır.
- Esneklik: Yeni bir işlev kolayca eklenebilir.
- Temiz Kod: Eylem kontrolü ve işleme kodu ayrıştırıldığı için kod okunabilirliği artar.
Sonuç olarak, Chain of Responsibility Pattern ile Flutter uygulamanızda Method Channel çağrılarını yönetmek, tıpkı karmaşık bir kahve siparişini düzenlemek kadar eğlenceli ve düzenli olabilir. Şimdi kahvenizi alın ve kod yazmaya devam edin!
Umarım sizin için faydalı olur. :) Beni takip etmeyi unutmayın, desteğiniz ve geri bildirimleriniz benim için çok önemli, teşekkürler.
LinkedIn: https://www.linkedin.com/in/haydardemir/ GitHub: https://github.com/birhos
Keyifli kodlamalar!