前提
公式のGet startedを翻訳しつつも段階的に解釈して進めて行きます。
初学者向けのチュートリアルではありますが、これが何かしらの手助けになれればと思っています。個人的な所感もありますが、色々な方からの知見も吸収出来たら幸いです。まずはFlutterというのは何だろうから初めていきます。
Flutterって何?
Apache Cordova、ReactNative、Xamarinと同じようにクロスプラットフォーム開発を可能とするモバイルアプリケーションフレームワークです。言語についてはDartとなります。Dart2が発表されてからGoogleも本腰を入れて進めていると思います。一部では学ぶべき言語ではない、とも言われていますがaltJSの観点で言うと私は今後伸びて行くと思っています。紹介が終わった所で実際に動かして行きます。
目次
- Get startedを流していく
- Part1のテーマ
- Step 1: Create the starter Flutter app
- Step 2: Use an external package
- Step 3: Add a Stateful widget
- Step 4: Create an infinite scrolling ListView←こちらは次回
Part1はStep4までありますが、今回はStep3までを対象に実施していきます。
元ネタ
Get startedを流していく
オブジェクト指向コードや、変数、ループ、条件付きなどの基本的なプログラミングの概念に慣れている場合は、このFlutterのチュートリアルを完了することが出来る。感覚的にはJavaなどがつがつとやって来た方はDartに対しての苦手意識はなくなるでしょう。
Part1のテーマ
公式では以下の内容が羅列されています。
- iOSとAndroidのクロスプラットフォームにて不自然なく見えるアプリの書き方。
- Flutterアプリの基本構造。
- 機能拡張のためのパッケージ使用方法。
- ホットリロードの使用方法。
- stateful widgetを実装する方法。
- Lazy Loadのリスト作成方法(ページの表示を速くするための遅延読み込み)。
Step 1: Create the starter Flutter app
ここではシンプルなテンプレートを使用してFlutterのアプリの作成を行っていきます。作成されたコードを一部抜粋し、何が起きているかフォーカスを絞ってみようと思います。
※プロジェクト作成部分は割愛します。
class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( title: 'Welcome to Flutter', home: Scaffold( appBar: AppBar( title: Text('Welcome to Flutter'), ), body: Center( child: Text('Hello World'), ), ) ); } }
StatelessWidget
ステートレス、という事から可変でなく状態を持たない固定のwidgetを指しています。StatefulWidgetというモノもあり、これは可変で状態を持つというwidgetを指します。(後ほど出てきます)FlutterではStatelessWidgetを拡張して、アプリ自体をwidgetとして扱います。class [App名] extends StatelessWidget
としているのが該当コード部分ですが、なぜStatelessWidgetの中にStatefulWidgetが存在したりしているのかというと、複数のclassを内包した画面は最終的には不変となるモノなのでStatelessという位置付けです。BuildContext
についてはアプリケーションが起動してから終了するまでのライフサイクル、つまり1つの画面を統括する役割です。
いずれ深掘りしますが、最初から全てを知ろうとすると進まない原因となるので、ここは先へ進みたいと思います。どの言語でもFWでもそうなのですが、使われているパッケージなどの参照は勉強になるので恐れず深淵に進んで行きましょう。
参考:StatelessWidget class - widgets library - Dart API
Widget
Flutterでは、アプリのパーツのほぼ全てがwidgetという概念。
widget = 画面を構成する部品(UI)という意味。
参考:Introduction to widgets - Flutter
build
下位レベルのwidgetに関して表示する方法を記述するbuild()
メソッド(以下抜粋)を提供します。これはAndroidやiPhoneでもcontextな考えがあるので普段からアプリ開発を行っている方はとっつきやすいですね。多くの場面で呼ばれているのでこちらも今後深堀りしていきます。
参考:build method - State class - widgets library - Dart API
MaterialApp
MaterialWidgetと呼ばれるwidgetはMaterialDesignの原則に従っているwidgetの実装を指します。基本的に用意されているwidgetを使用することも出来るし、混在させる事も出来る。もちろん独自のcustom widgetの作成も可能。私はデザインセンスが絶望的に無いのでここに乗っかって行きたいと思います。
参考:MaterialApp class - material library - Dart API
Scaffold
Scaffoldは単純な和訳で土台です。ここではMaterialDesign原則のwidgetを基本的な部品として使います。Railsを使った事がある方は聞き覚えのある言葉でしょうが、Flutterはモバイルアプリケーションフレームワークなのでコンセプトは少し違います。widgetの足場としてwidgetを積み上げていきます。
参考:Scaffold class - material library - Dart API
Step1はこれ終了です。ここまで消化出来ました。
- iOSとAndroidのクロスプラットフォームにて不自然なく見えるアプリの書き方。
Flutterアプリの基本構造。- 機能拡張のためのパッケージ使用方法。
- ホットリロードの使用方法。
- stateful widgetを実装する方法。
- Lazy Loadのリスト作成方法(ページの表示を速くするための遅延読み込み)。
ガンガン進んで行きましょう。
Step 2: Use an external package
ここではOSSパッケージのenglish_wordsを使用する方法の説明です。pubspec.yaml
のdependencies
部にenglish_words: ^3.1.0
を追加します。
dependencies: flutter: sdk: flutter cupertino_icons: ^0.1.2 english_words: ^3.1.0 # こちらを追加
追加後にAndroidStudioだとPackage get
などサジェストが出てくるのでこちらを実行しても良いです。これを実行した場合はflutter pub get
を内部で行ってくれています。手動で行う場合は以下のコマンドを実行します。
$ flutter pub get
english_wordsはpubspec.lock
にも自動生成されます。試しにpubspec.yaml
から外して再度Package get
などするとここからpubspec.lock
から除外されていることも確認出来ます。
パッケージの追加が終わったので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) { // importしたpackageを使う final wordPair = WordPair.random(); return MaterialApp( title: 'Welcome to Flutter', home: Scaffold( appBar: AppBar( // ここではキャメルケースで試して見ます title: Text(wordPair.asCamelCase), ), body: Center( child: Text('Hello World'), ), ) ); } }
アプリを実行します。アプリが実行中の場合は、実行中のアプリを更新するためにホットリロードが走ります。プロジェクトを保存してもホットリロードが行われます。
基本的なパッケージの使い方
ここは正直あまり掘り下げる必要がないと思っています。どの言語でもFWでも様々な外部パッケージやらライブラリは必要不可欠ですのであくまでランダムな単語構成を作るためにenglish_wordsを使用しているくらいの感覚です。
Step2はこれで終了です。ここまで消化出来ました。
- iOSとAndroidのクロスプラットフォームにて不自然なく見えるアプリの書き方。
Flutterアプリの基本構造。機能拡張のためのパッケージ使用方法。ホットリロードの使用方法。- stateful widgetを実装する方法。
- Lazy Loadのリスト作成方法(ページの表示を速くするための遅延読み込み)。
Step3へ進みましょう。
Step 3: Add a Stateful widget
Stateful widgetは、widgetが変更される可能性がある状態を維持します。 実装するには、少なくとも2つのクラスが必要です。
- StatefulWidgetクラス
- Stateクラス
まず、StatefulWidgetクラス(RandomWordsState)を作成していきます。main.dart
に追加します。
// StatefulWidgetクラス(RandomWordsState) class RandomWords extends StatefulWidget { @override RandomWordsState createState() => RandomWordsState(); } // Stateクラス(RandomWordsState) class RandomWordsState extends State<RandomWords> { @override Widget build(BuildContext context) { final wordPair = WordPair.random(); return Text(wordPair.asPascalCase); } }
State
widgetを構築するbuild()
を実行しているのでStateがwidgetの状態管理や構成を担ってくれています。ここはReactの良い部分をインスパイアしている感じが見受けられます。
StatefulWidget
Step3の冒頭で言っていた通り、StateクラスとStatefulWidgetクラスの2つで構成されています。StatefulWidgetはbuildメソッドを持たず、createStateメソッドを持ち、これがStateクラスを返します。
Stateful widgetの完成
MyApp
クラスでwordPair
を削除しRandomWords
を呼ぶように変更します。
class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( title: 'Welcome to Flutter', home: Scaffold( appBar: AppBar( title: Text('Welcome to Flutter'), ), body: Center( child: RandomWords(), ), ), ); } }
これでアプリを実行するとStep2と同様の動作となりますね。
Step3はこれで終了です。 ここまで消化出来ましたね。
- iOSとAndroidのクロスプラットフォームにて不自然なく見えるアプリの書き方。
Flutterアプリの基本構造。機能拡張のためのパッケージ使用方法。ホットリロードの使用方法。stateful widgetを実装する方法。
次でPart1ラストのStep4です、が!これは次回に持越したいと思います。
所感
元々DroidKaigi 2018で発表された際に気になってはいたのですが、実際にチュートリアルを少しやっているとツリー構造もイケてるし、野良パッケージも少なさそうです。最初のハードルとしては少し高いように感じますが、理解が追いついた時にかなりの生産性を発揮してくれるでしょう。実際、Native側の開発者からも「良さげ」という評価が高いです。少し懸念的な部分を持つとすればiOSでのUI部分はネックそうだなと…と言うのも冒頭で iOSとAndroidのクロスプラットフォームにて不自然なく見えるアプリの書き方とあるのですが正直な所、ここは言及されているようには思えなかったのが私の所感です。
次回
Part1のStep4を解説していきます。