FlutterのCallBackとは?
Overview
コールバックというのは、コールバック関数と呼ばれている関数を引数として、関数で使うことができるものというのが、よく技術記事で見かける表現です。
Dartのコールバックも同じものなのか深掘りしてみることにしました。
Signature of callbacks that have no arguments and return no data.
引数を持たず、データを返さないコールバックのシグネチャ。
typedefsというワードがでてきましたね?、これはなんでしょうか?、Dartの公式リファレンスを見て調べてみました。
Typedefs(型定義という意味)
A type alias—often called a typedef because it’s declared with the keyword typedef—is a concise way to refer to a type. Here’s an example of declaring and using a type alias named IntList:
型エイリアスは、typedefというキーワードで宣言されるため、typedefと呼ばれることもありますが、型を参照するための簡潔な方法です。ここでは、IntListという名前の型エイリアスを宣言し、使用する例を示します。
typedef IntList = List<int>;
IntList il = [1, 2, 3];
A type alias can have type parameters:
型エイリアスは、型パラメータを持つことができる。
typedef ListMapper<X> = Map<X, List<X>>;
Map<String, List<String>> m1 = {}; // Verbose.
ListMapper<String> m2 = {}; // 同じことでも、より短く、より分かりやすく.
Version note: Before 2.13, typedefs were restricted to function types. Using the new typedefs requires a language version of at least 2.13.
バージョン情報:2.13以前は、型定義は関数型に限定されていました。新しい型定義を使用するには、少なくとも2.13の言語バージョンが必要です。
We recommend using inline function types instead of typedefs for functions, in most situations. However, function typedefs can still be useful:
ほとんどの場合,関数の型定義は使用せず,インライン関数型を使用することをお勧めします.しかし、関数の型定義はまだ役に立つことがあります。
typedef Compare<T> = int Function(T a, T b);
int sort(int a, int b) => a - b;
void main() {
assert(sort is Compare<int>); // True!
}
Typedefsがあるといいこと!
関数に型を定義することができる。今回だとボタンコンポーネントに、VoidCallback型の変数を作成して、コールバック関数に渡すことができる関数の型を指定できる。
void型の関数は渡せるけど、int型の関数を引数として渡すとエラーが発生する。
切りわけたWidgetクラスに関数を引数として渡して、ボタンを押すとカウンターが増えるのと、トーストを出すプログクラムを作ってみました!
カウンターだけだと面白くないですよね😅
こちらのパッケージを追加
もしビルドしてエラーが出たら、アプリを一度削除してもう一度ビルドすると治ります?
トースト独特のエラーのようです🤔
完成品のコード
import 'package:flutter/material.dart';
import 'package:fluttertoast/fluttertoast.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: const CallbackExample(),
);
}
}
class CallbackExample extends StatefulWidget {
const CallbackExample({Key? key}) : super(key: key);
State<CallbackExample> createState() => _CallbackExampleState();
}
class _CallbackExampleState extends State<CallbackExample> {
int count = 0;
// コールバック関数に引数として渡す関数
void increment() {
setState(() {});
count++;
// fluttertoastのコード
Fluttertoast.showToast(
msg: "callback $count",
toastLength: Toast.LENGTH_SHORT,
gravity: ToastGravity.CENTER,
timeInSecForIosWeb: 1,
backgroundColor: Colors.red,
textColor: Colors.white,
fontSize: 16.0);
}
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Callback$count'),
),
floatingActionButton: VoidCallbackButton(callback: increment),
);
}
}
// FloatingActionButtonを切り分けたWidget
class VoidCallbackButton extends StatelessWidget {
const VoidCallbackButton({
super.key,
required this.callback,
});
// VoidCallback
final VoidCallback callback;
Widget build(BuildContext context) {
return FloatingActionButton(
onPressed: callback,
tooltip: 'Increment',
child: const Icon(Icons.add),
);
}
}
実行結果
まとめ
コールバックは、どんな場面で使うかというと、Widgetを切り分けて部品化してあるWidgetクラスやメソッドに引数として渡すときです。
覚えておくと使う機会があると思うので、皆さんもコールバックでプログラムを作るのをやってみてください。
Discussion