リバース・エンジニアリング

Flultterとテックブログと時々iOS

24. Flutterでの関数の型プロパティFunctionの導入と関数の初期化の方法

今回はFlutterで関数をプロパティのように扱う方法について学習します。 簡単にいえば、Function型が存在することが理解できればOKです。 用途はButtonクラスにonPressedプロパティがあるのですが、これをカスタムウィジェットにするときに使われるやり方です。

では、始めていきます。

サンプルコード

Flutterの場合、サンプルコードを書いたほうが早いので次のようなコードをイメージしています。

main.dart

import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatefulWidget {
  @override
  State<StatefulWidget> createState() {
    return _MyAppState();
  }
}

class _MyAppState extends State<MyApp> {

  int index;

  @override
  void initState() {
    index = 0;
  }
  /// こいつをRaisedButtonに渡すイメージ
  void _increment() {
    index = index + 1;
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text('My First App'),
        ),
        body: RaisedButton(
          child: Text('ファンクションのプロパティの練習'),
          onPressed: _increment,
        ),
      ),
    );
  }
}

画面にはRaisedButtonが表示されている感じです。 RaisedButtonのonPressed_incrementメソッドが渡されています。

今回はこの_incrementを例にして説明します。 単純にRaisedButtonをカスタムウィジェット化してonPressedの部分をプロパティ化します。

新しくcustom_raised_button.dartのクラスを作成します。

custom_raised_button.dart

import 'package:flutter/material.dart';

class CustomRaisedButton extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Container();
  }
}

それではcustom_raised_button.dartRaisedButtonを移動させます。

custom_raised_button.dart

import 'package:flutter/material.dart';

class CustomRaisedButton extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return RaisedButton(
      child: Text('ファンクションのプロパティの練習'),
      onPressed: _increment,
    );
  }
}

この時点では_incrementのメソッドは存在しないよ、というエラーが出てしまいます。

これが今回のテーマの本質になります。 前回、カスタムウィジェットの作成の仕方を学習しましたがそれと同じことをします。

  1. Functionを型とするプロパティを宣言する
  2. 初期化の際にプロパティのコンストラクタを宣言する

これだけです。

それではcustom_raised_button.dartを次のように修正します。

custom_raised_button.dart

import 'package:flutter/material.dart';

class CustomRaisedButton extends StatelessWidget {
  /// 1. Funciton型のプロパティを宣言する
  final Function increment;

  /// 2. コンストラクタにプロパティを宣言する
  CustomRaisedButton(this.increment);

  @override
  Widget build(BuildContext context) {
    return RaisedButton(
      child: Text('ファンクションのプロパティの練習'),
      onPressed: increment,
    );
  }
}

これでエラーが解消されてビルドが成功するようになります。 DartではFunction型のプロパティを持つことができることによる用法ですね。

Swiftではクロージャーの変数を持つことができますが、DartではFunctionの変数が持つことができるわけです。 そして、Flutterでの開発ではウィジェットの粒度はなるべく薄くすることが求められるので、 今回学んだテクニックでボタンウィジェットも切り離すことができるようになりましたね。