はじめに
iOSメインのスマホアプリエンジニアです。
iOSエンジニア視点からFlutterのコールバックの利用タイミングなどを自分なりにまとめました。
Dartの文化に反していたり、好みや等があるかもしれませんがご了承ください。
その他ご意見ございましたらご指摘ください。
VoidCallback
最もシンプルでFlutter callback
と検索すると真っ先に引っかかるコールバック方法です。
その名の通り、「空っぽのコールバック」
宣言
VoidCallbackを受ける側の実装。
voidCallback = (){
print("voidCallback");
};
呼び出し
VoidCallbackを呼び出す
voidCallback.call();
// 以下でも可能。
voidCallback();
利用用途
明示的に「このコールバックには引数がないですよー」と表したいときに利用する。
ただ、後述のFunction
で事足りるため、チーム内で統一するために使わないようにするのも良いと思いました。
#Function
コールバックを呼び出すタイミングで何かしらパラメータを渡したいことが多いと思います。
そのときに登場するのがこちらのFunction
になります。
##引数なし
宣言
受ける側の実装。
// 引数なし。VoidCallbackと同じ。
Function function1;
// 受ける側の実装。
function1 = (){
print("voidCallBack");
};
呼び出し
Function
を呼び出す
function1();
##引数あり
宣言
受ける側の実装。
// 引数ありのコールバック
Function(String) function1;
// 受ける側の実装。
function1 = (args){
print("function1 args:$args");
};
呼び出し
呼び出し側の実装。
function1("このパラメータが渡されます。");
##引数あり応用編
宣言
// 引数が複数のコールバック。
Function(int, String) function2;
function2 = (args1 , args2){
print("function2 args1:$args1 args2:$args2");
};
// 引数にクラスを渡す。
class Hoge {
final String name;
final int age;
Hoge({this.name, this.age});
}
Function(Hoge) function3;
function3 = (hoge){
print("function3 name:${hoge.name} age:${hoge.age}");
};
呼び出し
// 引数が複数のコールバックを呼び出す。
function2(111 , "function2の引数が渡されます。");
// 引数がクラスのコールバックを呼び出す
function3(Hoge(name: "name" ,age: 20));
利用用途
iOSでいうBlock
やClosures
に似ており、単一のコールバックを返すに適していると思います。
複数のコールバックを返したい場合に、メンバー変数等に宣言すると冗長になります。
Delegateみたいなこと出来ないかな。と探しましたところありました!
#mixinを使ったDelegateパターン
mixin
を使ったDelegate
パターンを使って実装してみましたところ、iOSエンジニアから見ると非常に馴染み深い書き方になります。
今回はStatefulWidget
に記載する例を記載しました。
宣言
// iOSで言うところのprotocolを宣言。
mixin HogeDelegate {
void hoge();
void hogeHoge1(String);
void hogeHoge2(String args1, String args2);
String hogehoge4();
}
// クラスにDelegateを作成。
class Hoge {
HogeDelegate delegate;
void run(){
delegate.hoge();
}
}
// Stateクラスに受け取れるように実装します。
// with HogeDelegate追加。
class _MyHomePageState extends State<MyHomePage> with HogeDelegate {
// Hogeクラスを宣言。
Hoge hogehoge;
void hoge() {
print("delegate hoge");
}
void hogeHoge1(String) {
print("delegate hogeHoge1");
}
void hogeHoge2(String args1, String args2) {
print("delegate hogeHoge2 args1$args1 $args2");
}
String hogehoge4(){
return "hogehoge4を返却する。";
}
@override
void initState() {
super.initState();
// initでクラスとdelegateを宣言しておく。
hogehoge = Hoge();
hogehoge.delegate = this;
}
}
呼び出し
hogehoge.run();
#まとめ
個人的には以下のように使い分けてみようかと思います。
概要 | iOSでは? | 使いみち |
---|---|---|
VoidCallback | iOSではない | 明示的にパラメータ等を返さないと宣言したい時に利用する。 |
Function | Block/Closures | 単一のコールバックを返すに適している。複数のコールバックをFunctionで実装すると冗長になる可能性がある。 |
mixin | Delegate | TableViewDelegateのように、複数のコールバックを返却したいときに適している。 |
その他のコールバックを見つけたら追記していきたいと思います。