こんにちは!Mukaigaです。
約3年前まで可茂IT塾でインターンしており、その時はFlutterでアプリ開発をお手伝いさせていただいておりました。 しかし、その後は業務委託、新卒での会社などでNext.jsやRailsを使用しており、すっかりweb方面ににシフトしてしまいました。
日頃、企業向けのサービスを開発しておりますが、個人としてはやはりエンタメ・サブカル等のジャンルなど、私生活に関わるアプリ作りに関わりたいです。
そこで個人開発として、久々にアプリに手を出そうと思いましたが、いざやろうとしたらすっかりFlutterが抜けていたので、復習してみます。
Flutterアプリの基礎中の基礎を思い出す。
まずは、Getting startedを求めて、公式HPでもみていきましょう。
おー、なんかカッコいいですね!特に真ん中のモノトーンの車のアプリ、デザインが好みです。
早速右上に、get startedを見つけました。
書いてある通りに、環境構築を進めていきます。
RecommendedにVSCodeで、Flutter拡張を使うのが良いとありますね。
以前はAndroid studioを使用していましたが、今回はVSCodeにしてみます。
$ flutter doctor
flutter doctorを使用すれば、不足している問題を教えてくれそうです。すごく懐かしい。
一箇所Android toolchain
って言うのがバツになっています・・・
今回Androidは考えていないので、多分大丈夫と信じて先に進みましょう。
早くコードを見たいです。
次のステップは、アプリを作る見たいです。codelabに飛ばされ、そこにチュートリアルがありました。
https://codelabs.developers.google.com/codelabs/flutter-codelab-first?hl=ja#0
ここにも環境構築がありました。
コマンドパレットから、新しいプロジェクトを作成できそうです。
おー、一瞬でベースが作成されました!面白い!
右下の赤枠から、IOSシュミレーターを起動したて、デバッグを開始してみます。
本当に久しぶりで、ほぼ初めてな気分なので、コードを丁寧に読んでいきます。
昔なら読み飛ばしていましたが、最近は地道にコードを理解していくことが重要だと気づいたので(当たり前のことかもですが。)読みます。
コメントが英語で書かれています。自分は英検準二級ですが、読めなかった(気分的に)ので翻訳をかけています。
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
// This widget is the root of your application.
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
// これはアプリケーションのテーマです。
//
// これを試してみてください: flutter run "でアプリケーションを実行してみてください。すると
// 紫色のツールバーが表示されます。次に、アプリを終了せずに
// 下のcolorSchemeのseedColorをColors.greenに変更してみてください。
// アプリを終了せずに、 // 以下のcolorSchemeのseedColorをColors.greenに変更してみてください。
// を押すか、コマンドラインを使った場合は 「r 」を押してください。
// カウンタがゼロにリセットされなかったことに注目してください。
// アプリケーションの状態はリロード中に失われません。状態をリセットするには、代わりにホット
// 再起動を使用してください。
//
// これは値だけでなく、コードにも有効です: ほとんどのコード変更は
// ほとんどのコード変更はホットリロードだけでテストできる。
colorScheme: ColorScheme.fromSeed(seedColor: Colors.green),
useMaterial3: true,
),
home: const MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
まずはこの部分です。
void main() {
runApp(const MyApp());
}
おそらく、アプリのエントリーポイントです。 runApp
で定義されたMyApp
を実行しているようです。
class MyApp extends StatelessWidget {
const MyApp({super.key});
classで定義されたMyAppがあり、それはStatelessWidgetを継承していそうです。
StatelessWidgetが気になったので、調べてみましょう。
Flutter Docsに記述がありました。 https://docs.flutter.dev/get-started/fundamentals/widgets
翻訳をかけると次のように書かれています。
フレームワークは、ステートフルウィジェットとステートレスウィジェットという2つの主要なクラスのウィジェットを導入する。
ミュータブルな状態を持たないウィジェット(時間の経過とともに変化するクラスプロパティを持たない)は、StatelessWidgetのサブクラスです。Padding、Text、Iconなど、多くの組み込みウィジェットはステートレスです。独自のウィジェットを作成する場合、ほとんどの場合、ステートレス・ウィジェットを作成します。
一方、ウィジェットの固有の特性が、ユーザのインタラクションやその他の要因に基づいて変更される必要がある場合、そのウィジェットはステートフルです。たとえば、ユーザがボタンをタップするたびに増加するカウンタがある場合、カウンタの値がウィジェットのステートになります。この値が変更されると、UI の一部を更新するためにウィジェットをリビルドする必要があります。これらのウィジェットは、StatefulWidgetのサブクラスで、(ウィジェット自体はイミュータブルなので)ミュータブルなステートをStateのサブクラスである別のクラスに格納します。StatefulWidgetは、ビルド・メソッドを持ちません。代わりに、下の例に示すように、ユーザー・インターフェースは、Stateオブジェクトを通してビルドされます。
なるほど、StatufulWidgetは状態を持ち、再描画されるんですね。ちょっと思い出してきました。
実際MyApp
は状態を持っていなさそうで、StatelessWidetなのも納得です。
次に気になるのはこちらでしょうか。
return MaterialApp(
サンプルコードには、MaterialAppの定義はありません、なので用意されたクラスでしょうか。
https://api.flutter.dev/flutter/material/MaterialApp-class.html
api.flutter.devにありました。
チラッとoptionsを眺めていたら、DEBUGバナーを消せそうなものがありました。
debugShowCheckedModeBanner → bool Turns on a little "DEBUG" banner in debug mode to indicate that the app is in debug mode. This is on by default (in debug mode), to turn it off, set the constructor argument to false. In release mode this has no effect.
class MyApp extends StatelessWidget {
const MyApp({super.key});
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
debugShowCheckedModeBanner: false, // 追加
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(seedColor: Colors.green),
useMaterial3: true,
),
home: const MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
消えました。スッキリ。
他にも気になる部分は多いですが、長くなるので今回は目的を達成するために進めます。
早速、目的である、コンポーネントの分離をやってみます。 コンポーネントと呼ぶべきではないかもしれません、ウィジェットと呼びます。
MyHomePageを別ファイルに分けてみます。
Flutterチュートリアル(codelabのやつ)にやり方がありました。
Refactorメニューから、Extract Widgetを選択すると、自動で分離してくれるようです。
おお!すごい、my_home_page.dartが作成され、そこにMyHomePageクラスが移動されました。
main.dart は以下のようになりました。
import 'package:flutter/material.dart';
import 'package:flutter_tutorial/my_home_page.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
debugShowCheckedModeBanner: false,
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(seedColor: Colors.green),
useMaterial3: true,
),
home: const MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
勝手にこちらのimportが追加されました。
どうやら、importで相対パスを記述することで、他のファイルを読み込むことができるようです。
import 'package:flutter_tutorial/my_home_page.dart';
一方で、切り出したmy_home_page.dartは以下のようになりました。
import 'package:flutter/material.dart';
class MyHomePage extends StatefulWidget {
・・・
importパスは、material.dartしかありません。呼び出し側のみにあれば良さそうです。
これはNext.jsに近く、理解しやすいですね。
やり方がざっくり分かったので、次はページ遷移をやってみます。
おそらく、必要なのは以下でしょうか。
まずはボタンの用意からしてみます。 https://docs.flutter.dev/ui/widgets/material ここにありました。
他にも色々なウィジェットがあり、とても面白そうです。
my_home_page.dartのColumnに、ボタンを追加してみます。
children: <Widget>[
const Text(
'You have pushed the button this many times:',
),
Text(
'$_counter',
style: Theme.of(context).textTheme.headlineMedium,
),
FilledButton(
child: const Text('次のページへ'),
onPressed: () {
// ...
},
できました!
次に、遷移先のページを作成します。
test_page.dartを作成し、以下のようにしてみました。
import 'package:flutter/material.dart';
class TestPage extends StatelessWidget {
const TestPage({super.key});
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Text(
"This is a test page",
),
),
);
}
}
そして、先ほど追加したボタンのhandlerに、遷移するロジックを書きます。
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => const TestPage()),
);
},
遷移でき、test_pageが作成できました!
今回は、基礎中の基礎をやってみました。
ネイティブアプリを自分でも作れると思うと、ワクワクしますよね!
まだまだアプリ開発する上では全然知識が足りたいので、コツコツ進めていきたいです。
可茂IT塾ではFlutter/Reactのインターンを募集しています!可茂IT塾のエンジニアの判断で、一定以上のスキルをを習得した方には有給でのインターンも受け入れています。
Read More可茂IT塾ではFlutter/Reactのインターンを募集しています!可茂IT塾のエンジニアの判断で、一定以上のスキルをを習得した方には有給でのインターンも受け入れています。
Read More