Closed19

Flutterを勉強し始めたので知ったことをメモしていく その1

ichi3wichi3w

このスクラップでは、Flutterを勉強し始めて知ったことを、つらつら垂れ流してみます。
目的は、知ったことを忘れないようにメモしておくことです。

もしかしたら、ざっと辿っていただけると、これからFlutterを学ぶ人は、なんとなく全体像が掴めるかもです。

あとは、個人のアウトプットとして垂れ流していくので、間違った情報があるかもです。
ご注意いただければ幸いです🕊

Flutter: 3.24.0
Macbook M1Pro
VisualStudio Code
iOS と Android 向けのアプリを作る

ichi3wichi3w

flutter開発環境のセットアップまで

概ね以下の通りでよさそうでした。
https://docs.flutter.dev/get-started/install/macos/mobile-ios

flutterのバージョン管理には、FVMを使いました。(ASDFを使うこともできそうです)
brew経由でインストール。

CocoaPods のインストールにruby が必要で、ただmacに入っているデフォルトのものはバージョンが低くて動かなかったので、rbenv でアップデートしました。
CocoaPods は iOS系の開発パッケージを管理してくれるらしいと雑に理解🤔

fvm flutter doctor でうまく動いているかチェックできたので、それに従って XCode や Android Studio を整えていきます。

IDEとしては、VSCodeを使うことにしました(ドキュメントを見ていると一番おすすめっぽかった)。

あとは、開発中のアプリを確認するために、Simulator.app をセットアップ(XCodeについてくるやつ)。実機を使うこともできるので、また開発に慣れてきたところでセットアップします。

ichi3wichi3w

fvmの使い方

いかにお世話になりつつ、ざっと使い方を把握しました。
https://github.com/leoafarias/fvm
https://zenn.dev/altiveinc/articles/flutter-version-management-3

fvm releases でインストールできるバージョンの一覧がわかります。
その後に、fvm install [VERSION] でPCにインストールできます。

プロジェクトで使うバージョンを決めるには、ディレクトリに移動して fvm use [VERSION] をします。

現在設定しているバージョンで、flutterコマンドを使うには、fvm flutter コマンド のようにします。

また、GLOBALに使えるflutterを設定するには、fvm global [VERSION]
もし、GLOBAL設定を解除するには fvm global --unlink です。
ただし、あらかじめパスを通しておく必要あるらしいです。

fvm list で現在インストールしているバージョンがわかります。
fvm doctor でいろいろ設定がわかります。

ichi3wichi3w

プロジェクトの作成

アプリを作成します。

VSCodeの拡張機能を入れていると、確か Command + Shift + P で flutterのアプリを作成することができました。
ほか、CLIでは以下で作成できました。
(いずれの方法も、flutterの docを参照するとよい)

fvm flutter create [プロジェクト名]
💡プロジェクト名にはハイフンが使えません。プロジェクト名がそのままパッケージ名になり、パッケージ名にはハイフンが使えないからです。

その後、 fvm use 3.24.0 をしてバージョンを固定しました。
正しくできると、gitignoreに.fvmが追加されたり、setting.json、.fvmrcが作成されました。
(これで異なる環境へのシェアできるかわかりませんが、取り急ぎ)

あとは、VSCodeの実行とデバッグから、flutter dart構成を選択しました。
ボタンを適当に押して、launch.jsonを適当に作ってもらいます。

最後に git init をして、適当にコミットを固めておきます。

💡バックエンドとして機能させるアプリと、このFlutterのアプリをモノレポにして管理したかったのですが、VSCodeのデバッグ機能の構成に不安を覚えたため、リポジトリを分けることにしました。またチャレンジしてみたいところです。

ichi3wichi3w

dartについて

https://dart.dev/

オブジェクト指向。
型安全(nullもちゃんとチェックしてくれる)。
さまざまなOSのアプリに対応するためか、class周りでそれなりに高度な表現がありそう?
C# と TypeScript を足して 3で割ったような印象を受けました🤔

以下、気になったところメモ

  • C# みたく var で変数を定義でき、自動で型推論してくれる
  • Stringとか型がある。型安全
  • null許容型じゃないとnullになれない
  • final をつけて変数を定義すると今後値を変更できなくなる
  • constはコンパイル時の定数
  • assartを使えば、開発環境でのみassartできる
  • print()でなんかprintできるらしい
  • @override @pragma @deprecated @Deprecatedのメタデータがある
  • _はプライベート、get,setとかもある
  • importは次のような感じ import 'package:lib2/lib2.dart' as lib2;
  • コレクションやintやmapやrecordなどの型がある
  • ジェネリックもある
  • 型定義はtypedefやけど、ほとんどの場合インライン関数で宣言するのがおすすめ
  • パターンマッチングとかできる。var (a, [b, c]) = ('str', [1, 2]);
  • 真のオブジェクト指向でFunction型もある
  • ループやifもある
  • エラーを投げたりtry catch でき、} on OutOfLlamasException { のようにExceptionに応じて処理もできる
  • dartのdevtoolがあるっぽいが、また調べる( https://dart.dev/tools/dart-devtools
ichi3wichi3w

dartのパッケージについて

pubパッケージマネージャで管理されているとのこと

よく使われるパッケージ
https://dart.dev/resources/useful-packages

Flutterの書き方をちょっと理解できたら、どんなものがあるか頭にざっと入れておきたいと思います。

ichi3wichi3w

アプリをデバッグで立ち上げる

Command + Shift + P のち「Flutter: Select Device.」を選択します。
もしくは、flutter devices コマンドで、使用できるデバイスを表示、選択します。

あとは F5 もしくは flutter run でデバッグを開始できました。

hot reloadあります!やったね!
(VSCodeなら hot reloadをクリック。cliから立ち上げた場合 r を入力)

https://docs.flutter.dev/get-started/test-drive

追記
lib/main.dart を開いて、VSCodeの画面右上の虫さんをクリックでも、アプリが起動するらしい。

ichi3wichi3w

はじめてのFlutterアプリ 1〜4くらい

以下をやっていきます。
https://docs.flutter.dev/get-started/codelab
ひとまず 1〜4ぐらい。

  • pubspec.yaml に現在のバージョン、依存関係など、アプリの基本情報があります
  • pubspec.yaml のdependencies を更新したら、自動でパッケージもダウンロードされました
  • analysis_options.yaml に lint設定があります
  • lib/main.dart から起動します

print('button pressed!'); をしたら、devtoolにログが出てきました。
ログがちゃんと出ると嬉しいですね。


ウィジェットはFlutterアプリを作成する際に、元となる要素とのこと。
ここら辺で、ウィジェットを組み合わせてアプリを作るのだと閃く!

buildメソッドはウィジェットか、ウィジェットのネストしたツリーを返します。


サンプルアプリでは、ChangeNotifierを継承して、MyAppStateクラスを作り、アプリの状態管理をしています。そして、各ウィジェットのbuildメソッドで、watchするようです。

ここらへんまでは、手続き型と宣言型が混ざったような感じでちょっと不思議です。


今回出てきたウィジェット

  • StatelessWidget
    • なんかアプリの大元になるやつ
  • Scaffold
    • なんか足場になるらしいやつ。便利でよく使われる
  • Column
    • 上から下へ、任意の数の子🐟を並べてくれる
  • Text
    • その名の通り文字を表示する
  • ElevatedButton
    • 何が Elevate かわからないが、とりあえずボタン。他のボタンが出てきた時に、このこの特徴もわかるはず
ichi3wichi3w

はじめてのFlutterアプリ その4〜5くらい

VSCodeのエディターでTextを右クリックして「リファクター > Extract Widget」をすると何ということでしょう、ウィジェットとして分離されました。

同じくリファクターで「Wrap with Padding」を選択すると、Paddingウィジェットが追加されました。

Flutterではできる限り継承ではなく合成をするらしい。
PaddingがTextの属性ではなく、ウィジェットとして分かれているのもそのためとのこと。
(..Flutterが少し好きになった)

リファクタ、でええ感じにしてくれるのはありがたいですね。
リファクタをぽちぽちしているだけで、知識が増えそうです。
ショートカットは「Ctrl + Shift + R」。


Widget build(BuildContext context) {
  final theme = Theme.of(context);

  return Card(
    color: theme.colorScheme.primary,
    child: Padding(
  // ...

のようにThemeから色を取り出して当ててみたり

色の変化を暗黙的にアニメーションくれるので、Themeを使うと良いそうです。

あとは、fontSizeを

final style = theme.textTheme.displayMedium!.copyWith(
  color: theme.colorScheme.onPrimary,
);

で指定したり。

themeに何を設定しておくか、結構重要そうですね。


semanticsLabel でスクリーンリーダーに対応するらしい。
Semantics というウィジェットもあるらしく、アクセシビリティは結構重要視されているとのこと。
https://zenn.dev/mjhd/articles/88c32b1610ca95


mainAxisAlignment: MainAxisAlignment.center,
を Column ウィジェットに設定すると、コンテンツを中央に配置できた。

おそらく、レイアウト用のウィジェットが他にもありそう。

あとは、devtool の Widget Inspector で Chromeの開発ツールみたく、要素の位置を見れました。
devtool を活用できるかで、けっこう得られる情報が増えそうなので、しっかり触っておきたい気がします。


今回出てきたウィジェット

  • Card
    • カードっぽい見た目になる
  • Padding
    • Paddingを入れてくれる
  • Center
    • 中央に寄せてくれる
  • SizedBox
    • 要素間スペースを

その他

適当に const やら final を使うと、メモリとかええ感じになってアプリが軽くなるらしいです。
うまく使っていく。

ichi3wichi3w

はじめてのFlutterアプリ その6

ビジネスロジックが現れたぞ! 編。


ジェネリクスを使って、 WordPair 以外が入らないようにした例。
var favorites = <WordPair>[];

型がある幸せの中で僕たちは生きていく。


mainAxisSize: MainAxisSize.min,

これで、そのコンポーネントのAxis のサイズを設定できました。
Center だったり、 mainAxisAlignment だったり、色々なサイズがある。

UWP の HorizontalAlignment とか、 CSS の flex とか、中央寄せ関係は「子要素にかかるか、自分の位置に影響するか」を掴むと早いと思っている。


ElevatedButton.icon(
  onPressed: () {
    appState.toggleFavorite();
  },
  icon: Icon(icon),
  label: Text('Like'),
),

appStateでは、notifyListenersでイベントを発しているぽい。
Reactみたく全自動(?)ではないが、UWPみたく長ったらしくPropertyChangedを作ったりせずともOK。

Flutterがまた好きになった。

ところで、appStateはどれくらいの粒度で分けておくのが幸せなのだろうか?


新しいウィジェット

  • Row
    • Columnがあれば、Rowもあるよね
ichi3wichi3w

はじめてのFlutterアプリ その7

ナビゲーションウィジェット編。
これで迷子にならずに済むのか、それとも迷子が発生する原因となるのか。


ナビゲーションを作るために。

よしなに SafeArea と Expanded を Row で振り分けながら、NavigationRail や これまでに作ってきたページを配置しました。

そして、ページは後述の ステートフルウィジェット をうまく使いながら、selectedIndex で切り替えていきます。


ステートレス ウィジェットとステートフル ウィジェット

これまではどのウィジェットも、自身にステートを持っていなかった。
すべて、ChangeNotifier を継承した、 MyAppState クラスを通して、状態を変化させていました。

せやかて Global な State を作りすぎると大変な目にあうことはわかっています。
そこで、 MyHomePage をステートフルに変えて、よしなにするらしい。

リファクタ機能を使い、ステートフルに変えると、_MyHomePageStateというプライベートなクラスが作られました。
これは State を拡張しているらしいです。

そして NavigationRail の

onDestinationSelected: (value) {
  setState(() {
    selectedIndex = value;
  });
},

で 選択された アイテムに切り替えるとのこと。
(setState 、、君はflutterにもいると思っていたよ、という気持ちです)
(flutterのStateクラスは、UWPのViewModel でよく使われる Observable class と似ているかも)

あとはええ感じに Widget の変数を作って、そこにページを入れて使ったらナビが機能するように。


ナビゲーションをレスポンシブ対応

大きさの単位として、flutterは論理ピクセルを使うとのこと。
ナビゲーション レール は画面のサイズを認知できないため、LayoutBuilder を使って、600px以上のサイズなら extended を trueにしてやります。

今回のナビゲーションレールでは使えませんが、ほかにもWrapやFittedBoxというウィジェットもあるらしいです。


今回出てきたウィジェット

  • SafeArea
    • その子がハードウェアノッチやステータスバーで隠れないようにしてくれる
  • NavigationRail
    • いわゆるナビゲーションバー
    • いくつかの Destination を含める
    • NavigationRailDestination でナビのアイテムを作れる
    • onDestinationSelected で Destination が選択された時に何が起きるかを書ける
  • Expanded
    • ええ感じにスペースを埋めてくれる。RowやColumnと仲良し
  • Container
    • 色のついたコンテナとか作れるよ
  • Placeholder
    • 名は体を表す
  • Wrap
    • 十分なスペースがない時に、自動的に次の行に子を送ってくれる
  • FittedBox
    • 指定に従って子を自動的に合わせる
  • LayoutBuilder
    • 画面サイズの制約に変更があった場合、builder コールバックが呼ばれる

気づき余談

ネスト祭りになりやすいぽい。

ichi3wichi3w

はじめてのFlutterアプリ その8

力試しとして、Favoritesを表示するページを作る。
以上

ichi3wichi3w

UWPやReactに触れたことはあるので、ウィジェットを使うとか、Stateを持たせるとか、宣言的UIとかは馴染みがありました。

慣れと覚えることはいくつかありそうだけど、とりあえず作り始めれそうです。

わからないことをざっとメモ

  • アプリが大きくなるにつれ、ハマりそうなことは?
  • 制約周りはまだ慣れが必要そう
  • MaterialUIを使うのでいいのか
  • ページとか別のファイルに分けたいな
  • 多人数の開発において、lintとかformatterとかどうしておくといいか?
  • 通信と非同期まわりのこと
  • データの永続化のこと
  • devtool使いこなす
  • テスト周り
  • OS特有の機能
  • アプリの公開について

アンチパターンをネットで拾っておきつつ、flutterのdocにざっと目を通し、作りたいものを作っていきながら調べる方向でいきます。

ichi3wichi3w

ブラウザのタブのロゴで、FlutterとZennを見間違える。

ichi3wichi3w

クパチーノとMaterial 3、どっちを使えばいいのだろうか、、?
さらに pub.dev には多くのデザインシステムもあるらしい🤔

デザインなだけで、使えるコンポーネントには差がない、と思いたいところです。
もし、Material 3 でしかできないことがあるなら辛いなぁと。
GoogleなのでMaterial 3を使っておけば、間違いなさそうですが、クパチーノを使いたい気持ちもあります。

そしてウィジェット一覧
https://docs.flutter.dev/reference/widgets

ichi3wichi3w

ひとまず以下の通りで試してみよう。

デザインシステムはAndroidとiOSともに対応したいので、MaterialUIを使う。
それでいて、徐々に自作のthemeで上書きしてやる。

状態管理(依存性注入)は新しすぎず、よく使われてそうな Provider と setState で。

なんとなくできそう感が出てきたので、ここまでとします。

このスクラップは4ヶ月前にクローズされました