Flutterで「子Widgetから親Widgetの処理を呼びたい」場合は、親の処理(コールバック)を子に渡して、子側で実行するのが基本です。
このときDartでは、関数型の変数は () でも .call() でも呼べます。
- まず結論:コールバックを子に渡す
親が「呼ばれたい処理」を用意し、子に渡します。
親(Parent)
import 'package:flutter/material.dart';
class Parent extends StatefulWidget {
const Parent({super.key});
@override
State<Parent> createState() => _ParentState();
}
class _ParentState extends State<Parent> {
String text = '';
void handleChange(String v) {
setState(() => text = v);
}
@override
Widget build(BuildContext context) {
return Column(
children: [
Text('text: $text'),
Child(onChanged: handleChange),
],
);
}
}
- 子(Child)側:onChanged.call(value) で呼べる
nullableじゃない(必須)コールバック
class Child extends StatelessWidget {
const Child({super.key, required this.onChanged});
final void Function(String value) onChanged;
@override
Widget build(BuildContext context) {
return TextField(
onChanged: (v) {
onChanged.call(v); // ← これ
// onChanged(v); // ← これと同じ
},
);
}
}
- 実務でよく使う:nullable + ?.call()(推奨)
Flutterのコールバックは ValueChanged? のように null(未指定)を許す設計が多いです。
その場合は ?.call() で安全に実行できます。
class Child extends StatelessWidget {
const Child({super.key, this.onChanged});
final ValueChanged<String>? onChanged;
@override
Widget build(BuildContext context) {
return TextField(
onChanged: (v) {
onChanged?.call(v); // nullなら何もしない
},
);
}
}
- () と .call() の違いは?
Dartでは関数型の変数は call メソッドを持つため、次は等価です。
onChanged(value)
onChanged.call(value)
ただし、nullable の場合に差が出ます。
onChanged?.call(value) は書ける
onChanged?.(value) は書けない
だからFlutterでは 「nullableコールバックを安全に呼ぶ用途」で .call() が頻出します。
まとめ
子から親の処理を呼ぶなら コールバックを子に渡すのが基本
Dartでは () と .call() は等価
Flutter実務では nullable対策として ?.call() が便利でよく使う