たなブログ 教養を高めて生涯資産を増やすブログ(`・ω・´)

【Flutter初心者】環境構築した後に学んでいくべき超基礎【Step③:ウィジェットを使用する】

Flutterを学ぶ PR

こんにちは、ちくたっく(@tictak_py)です。

今回も「Flutter環境構築をした後に学んでいくべき超基礎」の記事を書いていきたいと思います。前回は、外部パッケージを利用してランダムで生成された英単語を表示させる方法を解説してきました。

今回はウィジェットを使えるようにすることを目的とした第3回目の記事です。

  1. Hello Worldを表示させる
  2. 外部パッケージを使えるようにする
  3. ウィジェットを追加する
  4. スクロールするListViewを作る

ウィジェットというのはFlutterのUI(見た目)を構成している部品のことです。Flutterでアプリ制作する場合には、このウィジェットを組み合わせて複雑なUIを作り上げているため、ウィジェットの理解はとても重要と言えます。

今回も、第2回目と同様にランダムに生成された英単語を表示させるアプリを作りますが、ウィジェットの構成が違います。前回は「Stateless Widget」だけを使っていましたが、今回から「Stateful Widget」を追加してアプリを作っていきます。

こんな方に読んで欲しい記事です

  • flutterの環境構築をしたばかりの初心者の方
  • ウィジェットへの理解を深めたい方

ウィジェットへの理解を深める

先ほどもお伝えしたように、ウィジェットはアプリのUI(見た目)を構成している部品のことで、Flutterではこのウィジェットを組み合わせて複雑なUIを実現していくことになります。基本となるウィジェットには色々ありますが、ここでは大きく2つにわけたウィジェットを理解しましょう。

それは「Stateless Widget」と「Stateful Widget」の2つです。

Stateless WidgetとStateful Widgetを理解する

Stateless Widgetというのは、状態(State)を持たない(less)静的なウィジェットのことです。前の状態を維持しないもの、プロパティ(値)を変更する必要がないものといったイメージですかね。

Stateful Widgetというのは、状態(State)を持っている(ful)動的なウィジェットのことです。前の状態を維持するもの、プロパティ(値)を変更する必要があるものといったイメージになります。

よくわからないですね。公式ドキュメントにある具体例を見てみます。

公式ドキュメントにある記載より引用

青字で書いてある箇所が具体例になりますが、まとめるとこんな感じです。

  • Stateless Widget:アイコン、アイコンボタン、テキスト
  • Stateful Widget:チェックボックス、ラジオボタン、スライダー

アイコンボタンや決まったテキストであれば、その値を変更する必要はなさそうなので静的なStateless Widgetと言えそうですね。対して、チェックボックスやラジオボタンのようにユーザー操作によって値が変わりそうなものは動的なStateful Widgetと考えた方がよさそうです。

ちなみに、上記であげた具体例はそれぞれがウィジェットとなるので、Stateless WidgetかStateful Widgetのいずれかに配置していくことになります。

Stateless WidgetとStateful Widgetを実装する

Flutterアプリはウィジェットで構成されていて、主なウィジェットとしては静的なStateless Widgetと動的なStateful Widgetの2つがあることがなんとなくわかったら、実際にAndroid Studioで実装してみましょう。コードの大枠だけ理解していきます。

ここで知っておいて欲しいのは実装に必要な以下2つのコマンドです。

  • Stateless Widgetの実装:「stl」と入力して予測変換
  • Stateful Widgetの実装:「stf」と入力して予測変換

実際にAndroid Studioを起動し、main.dartファイルの下側空いている箇所で試してみてください。以下画像のようにいずれも「コマンド入力→予測変換→クラス名入力→クラス名決定」の流れでWidgetを作り上げることが出来ます。

Stateless Widgetの実装①|予測変換
Stateful Widgetの実装①|予測変換

Stateless Widgetの実装②|クラス名の入力
Stateful Widgetの実装②|クラス名の入力

Stateless Widgetの実装③|クラス名の決定
Stateful Widgetの実装③|クラス名の決定

左側がStateless Widgetで、右側がStateful Widgetですね。

左右で比べてみるとわかりますが、Stateful Widgetの方が少しコード量が多くなっています。これは、Stateful Widgetには①Stateful Widgetクラスと②Stateクラスの2つが必要となっているからです。まあ状態を管理する必要があるので、その分コードが多くなっているってことですかね。

以上の理解をもとに、今回も公式ドキュメントを参考に「RandomWords」というStatefulWidgetをアプリに組み込んで、ランダムに英単語が生成されるようにしていきたいと思います。

Stateful Widgetをアプリに組み込む

まずはmain.dartファイルにStateful Widgetを追加していきます。

前回記事の内容を引き継いでいるので、main.dartファイル内のコードは以下のようになっています。

import 'package:flutter/material.dart';
import 'package:english_words/english_words.dart';


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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    // ①:変数wordPairを追加
    final wordPair = WordPair.random();
    return MaterialApp(
      title: 'Welcome to Flutter',
      home: Scaffold(
        appBar: AppBar(
          title: const Text('Welcome to Flutter'),
        ),

        // ②:変数wordPairを先頭大文字で表示させる
        body: Center(
          child: Text(wordPair.asCamelCase),
        ),
      ),
    );
  }
}

もともとのコードに少し手を加えた状態になっていますが、現在は「Stateless Widget」しかないことがわかりますね。

前回はStateless Widgetの中で文字生成をしていましたが、今回はStateful Widgetを追加してその中で文字生成をしていくイメージとなります。

Random Wordsを作成する

では実際に「RandomWords」というクラス名でStateful Widgetを追加しましょう。以下のようなコードが追加されていればOKです。

class RandomWords extends StatefulWidget {
  @override
  _RandomWordsState createState() => _RandomWordsState();
}

class _RandomWordsState extends State<RandomWords> {
  @override
  Widget build(BuildContext context) {
    return Container();
  }
}

自動で入力、反映されるので便利ですが、いくつか補足しておきます。

まず、RandomWordsというWidgetはStateクラスを作成する以外には特に何もしていません。そして、Stateクラス名の先頭には自動で「_(アンダーバー)」が付いていますが、これはこういうものと割り切っておきましょう。一応、外部ファイルから参照できないようにプライバシー保護の役割があるらしいです。

StateクラスではRandomWordsの状態を引き継いでいることになり、アプリの重要なロジックやコードはこの部分に書かれることが一般的のようです。

_RandomWordsStateのbuildメソッドを書き換える

続いて、Stateクラスのbuildメソッド部分を以下のように書き換えていきます。

class _RandomWordsState extends State<RandomWords> {
  @override
  //buildメソッドの中身を書き換える
  Widget build(BuildContext context) {
    final wordPair = WordPair.random();
    return Text(wordPair.asPascalCase);
  }
}

前回、Stateless Widgetに書いていた処理をStateful Widgetに持ってくる感じですね。
あわせてStateless Widgetに書いていた処理を消して、RandomWordsクラスを呼び出す処理を加えておきます。

最終的に以下のようなコードになっていればOKです。

import 'package:flutter/material.dart';
import 'package:english_words/english_words.dart';


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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    // 以下を消す
    // final wordPair = WordPair.random();
    return MaterialApp(
      title: 'Welcome to Flutter',
      home: Scaffold(
        appBar: AppBar(
          title: const Text('Welcome to Flutter'),
        ),

        // 前回処理を消して、RandomWordsクラスへの処理を追加する
        body: Center(
          // child: Text(wordPair.asCamelCase),
          child: RandomWords(),
        ),
      ),
    );
  }
}

class RandomWords extends StatefulWidget {
  @override
  _RandomWordsState createState() => _RandomWordsState();
}

class _RandomWordsState extends State<RandomWords> {
  @override
  //buildメソッドの中身を書き換える
  Widget build(BuildContext context) {
    final wordPair = WordPair.random();
    return Text(wordPair.asPascalCase);
  }
}

この状態でAndroidエミュレータを起動してみてください。前回アプリと内容自体は変わりませんが、メイン機能をStateless WidgetからStateful Widgetに変更した上で動作させることが可能となりました。

さいごに

今回は、Flutterの中でも重要性の高いウィジェットについて解説してきました。

Stateless WidgetとStateful Widgetの違いを本質から理解するのは難しいと思いますが、実装を重ねていくうちに両者の違いがだんだんとわかってくるはずです。

Flutterアプリはウィジェットという部品の組み合わせでUIが構築されていること、ウィジェットには大きくわけて静的ウィジェット(Stateless)と動的ウィジェット(Statefule)の2つがあること、まずはここをしっかりと理解しておきましょう。

では今回はこのへんで。