PythonistがFlutterに触ってみた~Hello World編~
そうだ、Flutterに触ろう
なぜとか理由はない。
アプリを久しぶりに作ってみたくなったので、n番煎じだと思うが久しぶりにnoteを開いて備忘録を日記程度に書いていく。
なおFlutterにPythonは全然関係ないので、検索にヒットしてPythonでアプリ作りたいとかそういった思惑で読みにきた人は引き返すことをお勧めします。kivyとか触ればいいと思うよ。
以下を参考にしてます。
Part.1 開発環境の構築
インストール前の環境は以下の通り
OS: macOS 12.1
開発用ツール: Android Studio
デバッグ用のスマホ:Pixel6a
android version:13
インストールは、Flutterの環境構築について調べてヒットした記事(上記のもの)を参考にした。(なお今回はHPからダウンロードしてきたが、ちゃんと調べたらbrewが用意されていた。)
なお、Androidでしか動かさないが、一応xcodeをインストールしていなかったため、まずはApp storeからxcodeをダウンロードするところから始めた。
一応簡単な手順を書く
xcodeのインストール(iosで動かさないならいらない?)
flutterの公式からflutterをダウンロード
指定の箇所に置き、PATHを通す
GoogleがFlutterを作ったとはいえ、Android Studioでそのまま開発できるらしいから、無駄なインストールがなくなってよかったような、あのUIをまた使うのかという嫌悪感というかをこの時点で感じている。
Path通すのに少し手間取ったが、無事完了。
Part.2 Hello Flutter
まずはプロジェクトを作成
new Flutter Projectからprojectを作成。
どうやら、最初は先ほどインストールしたflutterに対してPathを設定する必要があるっぽい。勝手にPATHから拾ってこいよ
下のような感じで設定してみた(ほぼ初期通りだけどね)
よし、Finishだ。
ふぁっ!?Cannot Save Settings? アイエー,ドウシテー
とまぁ、茶番は置いておいて、must be a valid Dart package name ( lower_case_with_underscores )というように文字通り、小文字でしかDartのパッケージの名前はゆるさねぇからなということらしい。
名前をHellow_Flutterからhello_flutterに変更してFinish押したら無事通った。
こんな感じで<project名>/lib/main.dartに色々書くっぽい?
まずは、今の画面がどんな風なのかを確認するためにmacOSの画面をbuildしてみる。
おぉ….
参考にしたDartのHPでよくみたやつが出てきた。
+ボタンを押すと、0から1に変わった。
パーツについてみていく。
パッとみた感じ、
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
...build関数でMyHomePageをhomeに設定していた....
}
class MyHomePage extends StatefulWidget {
...結構普通のクラスっぽいけど、コンストラクタ無い。値を設定するだけならいらないっぽい...
...State<MyHomePage> createState()で\
...多分そのページで変数を作るためのStateオブジェクトみたいなものがつくれるっぽい...
}
class _MyHomePageState extends State<MyHomePage> {
...State<MyHomePage>をextendsしてるから、変数が作れるのかな?...
...incrementCounterという関数を持っていて、setState()の中でカウンターを増やしていた...
......どうやらsetStateの中で変えないとglobal変数は変えられないっぽい...
...buildという関数もあった。画面の構成とかボタンの設定を書く場所っぽい...
}
の4つでこの画面は構成されていた。
驚いたのが、javaやkotlinはオブジェクト指向言語なため、関数は必ずクラスに紐づいていたが、Dartだとmainのようにそのまま関数だけで置いてある点だ。
結構c-likeな印象をここで持ったが、継承の仕方はjavaとかそっちの方と同じなため、いいとこ取りな感じがする。
Pythonを普段使っている身からすると型付き言語久しぶりだなぁ。くらいの印象。
アプリの動きとしては、main.dartのmain関数でまずはMyAppクラスの内容でrunAppする。MyAppクラスは呼ばれたら、MaterialAppをhomeで指定した内容でbuildするみたいな感じかな?
次に画面の構成を司っているであろう、buildを詳しく見てみる。
@override
Widget build(BuildContext context) {
// This method is rerun every time setState is called, for instance as done
// by the _incrementCounter method above.
//
// The Flutter framework has been optimized to make rerunning build methods
// fast, so that you can just rebuild anything that needs updating rather
// than having to individually change instances of widgets.
return Scaffold(
appBar: AppBar(
// Here we take the value from the MyHomePage object that was created by
// the App.build method, and use it to set our appbar title.
title: Text(widget.title),
),
body: Center(
// Center is a layout widget. It takes a single child and positions it
// in the middle of the parent.
child: Column(
// Column is also a layout widget. It takes a list of children and
// arranges them vertically. By default, it sizes itself to fit its
// children horizontally, and tries to be as tall as its parent.
//
// Invoke "debug painting" (press "p" in the console, choose the
// "Toggle Debug Paint" action from the Flutter Inspector in Android
// Studio, or the "Toggle Debug Paint" command in Visual Studio Code)
// to see the wireframe for each widget.
//
// Column has various properties to control how it sizes itself and
// how it positions its children. Here we use mainAxisAlignment to
// center the children vertically; the main axis here is the vertical
// axis because Columns are vertical (the cross axis would be
// horizontal).
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
const Text(
'You have pushed the button this many times:',
),
Text(
'$_counter',
style: Theme.of(context).textTheme.headlineMedium,
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: _incrementCounter,
tooltip: 'Increment',
child: const Icon(Icons.add),
), // This trailing comma makes auto-formatting nicer for build methods.
);
}
英語がきちんと説明してくれているのでそこをそれぞれみていくと、
Widget build(BuildContext context) {
// This method is rerun every time setState is called, for instance as done
// by the _incrementCounter method above.
//
// The Flutter framework has been optimized to make rerunning build methods
// fast, so that you can just rebuild anything that needs updating rather
// than having to individually change instances of widgets.
return Scaffold(
appBar: AppBar(
// Here we take the value from the MyHomePage object that was created by
// the App.build method, and use it to set our appbar title.
title: Text(widget.title),
),
widgetを介せば、画面遷移とかで値の指定とかできるとかありそう。
body: Center(
// Center is a layout widget. It takes a single child and positions it
// in the middle of the parent.
child: Column(
child: Column(
// Column is also a layout widget. It takes a list of children and
// arranges them vertically. By default, it sizes itself to fit its
// children horizontally, and tries to be as tall as its parent.
//
// Invoke "debug painting" (press "p" in the console, choose the
// "Toggle Debug Paint" action from the Flutter Inspector in Android
// Studio, or the "Toggle Debug Paint" command in Visual Studio Code)
// to see the wireframe for each widget.
//
// Column has various properties to control how it sizes itself and
// how it positions its children. Here we use mainAxisAlignment to
// center the children vertically; the main axis here is the vertical
// axis because Columns are vertical (the cross axis would be
// horizontal).
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
const Text(
'You have pushed the button this many times:',
),
Text(
'$_counter',
style: Theme.of(context).textTheme.headlineMedium,
),
],
),
),
どちらかというと、html的なノリを感じる。
まぁ、ウェブページも作れるっぽいから当然か。
floatingActionButton: FloatingActionButton(
onPressed: _incrementCounter,
tooltip: 'Increment',
child: const Icon(Icons.add),
), // This trailing comma makes auto-formatting nicer for build methods.
なくても動くけど、そっちの方がいいんだろうな。
Part.3 Hello World!
というわけでColumnのchildren内を以下のように変更
children: <Widget>[
const Text(
'Hello World!!!!',
),
const Text(
'You have pushed the button this many times:',
),
Text(
'$_counter',
style: Theme.of(context).textTheme.headlineMedium,
),
],
),
),
Hello World!
ここも驚きポイントでどうやら変更は自動で再ビルドされるっぽい。
そしてめっちゃビルド早くて驚いた。Flutterの最適化の力ってスゲー!
感想
大体執筆時間含めて1.5時間くらいでできた。
多分環境構築して同じことをやるだけなら、30分もあればできると思う。
Flutter自体出始めの2018年から名前は聞いていたが、触ってみると案外取っ付きやすそうで良かった。
Pythonistが~ってタイトルだけど、Pythonとの違いはそこまで触れられていないのが今後の課題だな(そもそもそこまでPythonに詳しいかと言われるとどうなんだろうか….)
というか時間がない中なにやってんだ….
まとめ
Flutterのインストールはそこそこ手間(もしかしたらbrewあるかも?)
あったからこっち使えばストレスレスだと思う。
ビルドがめっちゃ早い!
Kotlinとかの最初のビルドはめっちゃ時間かかる印象あるからそれにくらべて何倍も早い印象。次々実装と実行結果が出るまでにタイムラグがないから集中して触れそう。
Dartは書き方はC-Likeだから、オブジェクト指向言語特有の取っつきづらさがない。
今後のTODO
-[ ] 画面遷移について
-[ ] ライブラリのインストールなどについて
-[ ] 簡単なアプリを作ってみよう
-[ ] ゲームエンジンについて
-[ ] APKのBuildの仕方について