「Write your first Flutter app, part 1」をしてみる!

 

最近よくみるFlutterでHello Worldしてみる

前回はFlutterを使ってHelloWorldをしたので、今回は。。。

Flutterの公式ドキュメントより、初めてのアプリを作ってみますー。わたしなりに日本語訳したのでお役に立てば嬉しいです^^

参照:
https://flutter.dev/docs/get-started/codelab

 

 

GithubにStepごとにプルリク分けたので良かったら参考にしてください。

https://github.com/kin29/flutter_first_app/pulls?q=is%3Apr+is%3Aclosed+

(おさらい)

ちょっと忘れかけていたので、appの新規作成とsimulatorでの実行方法をおさらいしておきます。分かる人は飛ばしてください😅

appの作成

$ flutter create myapp
$ cd myapp

simulatorを起動させておく

$ flutter emulators
2 available emulators:


Galaxy_Nexus_API_29 • Galaxy Nexus API 29 • Google • android
apple_ios_simulator • iOS Simulator       • Apple  • ios

To run an emulator, run 'flutter emulators --launch '.
To create a new emulator, run 'flutter emulators --create [--name xyz]'.

You can find more information on managing emulators at the links below:
  https://developer.android.com/studio/run/managing-avds
  https://developer.android.com/studio/command-line/avdmanager
$ flutter emulators --launch apple_ios_simulator

↑でapple_ios_simulatorが起動しますー

appのrun

simulatorを起動させておいた状態で、

$ flutter devices
1 connected device:

iPhone 11 • E1B5593C-D161-43EC-BD9D-733A9DC10494 • ios • com.apple.CoreSimulator.SimRuntime.iOS-13-4 (simulator)
$ flutter run
Launching lib/main.dart on iPhone 11 in debug mode...

Running Xcode build...

 └─Compiling, linking and signing...                        75.9s
Xcode build done.                                           100.4s
Syncing files to device iPhone 11...                               182ms

Flutter run key commands.
r Hot reload. 🔥🔥🔥
R Hot restart.
h Repeat this help message.
d Detach (terminate "flutter run" but leave application running).
c Clear the screen
q Quit (terminate the application on the device).
An Observatory debugger and profiler on iPhone 11 is available at: http://127.0.0.1:49386/TQwM5vCq3BY=/

simulatorに作ったappが起動しますー

では早速、はじめてのアプリを作っていきます🍻

 

Step 1: Create the starter Flutter app

lib/main.dartを以下に書き換える

// Copyright 2018 The Flutter team. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

import 'package:flutter/material.dart';

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

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'),
        ),
      ),
    );
  }
}

  • リターンしているMaterial(App)とは…?
    モバイルおよびWebの標準であるビジュアルデザイン言語で、Flutterには、いろんなマテリアルウィジェットのセットが用意されているらしい。
  • Statelessウィジェットを拡張している(Step3でStatefulウィジェットを使います)Flutterでは、配置、パディング、レイアウトなど、ほとんどすべてがウィジェットらしい。
  • Material(App)の中のScaffoldウィジェットは、デフォルトのアプリバー、タイトル、およびホーム画面のウィジェットツリーを保持するbodyプロパティを提供する。
  • ウィジェットの主な仕事は、ウィジェットを他の低レベルのウィジェットで表示する方法を説明するbuild()メソッドを提供する。
  • この例のbodyは、Text子ウィジェットを含むCenterウィジェットで構成されていて、 Centerウィジェットは、ウィジェットサブツリーを画面の中央に配置する。

Step 2: Use an external package

外部パッケージを使う例。pub.devにあるパッケージを使うことができる様子。
今回は例として「english_words」というパッケージを追加する。

2-1. pubspec.yamlの依存リストに追加する

pubspec.yaml

dependencies:
  flutter:
    sdk: flutter
...
+ english_words: ^3.1.0

2-2. pub get(package get?) をする

Android Studioのpub getをすると、$ flutter pub getが走るっぽい。
これが完了すると、pubspec.lockにもenglish_wordsの依存バージョン情報が追記される。

小ネタ

Waiting for another flutter command to release the startup lock…
がでる時の解決策

$ flutter pub get
Waiting for another flutter command to release the startup lock...

flutterコマンドのcacheにlockfileがあるのが原因らしいので、
/flutter/bin/cache/lockfileをrmすると解決しましたー🙇‍♂️ありがたい
参考:https://qiita.com/konifar/items/29f2ed4bcc2a970014c1

2-3. lib/main.dartに追加したパッケージ(english_words)を取り込む

lib/main.dart

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

2-4. english_wordsを使うコードを書く

lib/main.dart

               Widget build(BuildContext context) {            
+                final wordPair = WordPair.random();            
                 return MaterialApp(            
                   title: 'Welcome to Flutter',            
                   home: Scaffold(              
                       title: Text('Welcome to Flutter'),            
                     ),            
                     body: Center(            
-                      child: Text('Hello World'),            
+                      child: Text(wordPair.asPascalCase),            
                     ),            
                   ),            
                 );

ランダムに英語の単語がキャメルケースで表示されるようになりました!
hot reload⚡️すると単語が変わるのがわかりますー

 

Step 3: Add a Stateful widget

今の状態はStatelessウィジェットで、その名の通り不変なためプロパティの変更ができないためStatefulウィジェットを追加しますー
Statefulウィジェットは、ウィジェットの有効期間中の変化を維持できるらしいですー
Statefulウィジェットの実装には、StatefulWidgetクラスとStateクラスが必要らしい。
StatefulWidgetクラス自体は不変だが、Stateクラスが有効期間中の変化を維持してくれるらしい。

今後、Stateクラスを作るRandomWordsのStatefulウィジェットを追加し、そのRandomWordsを既存のMyAppステートレスウィジェット内の子として使用します。

3-1. main.dartにRandomWordsStateクラスを作成する

lib/main.dart

+ class RandomWordsState extends State<RandomWords> {
+   // TODO Add build() method
+ }

State<RandomWords>はRandomWordsでの使用に特化した汎用のStateクラスを使用していることを示してるらしい。
アプリのロジックと状態のほとんどはStateにあり、RandomWordsウィジェットの状態を維持する。
このクラスは、3-2(スクロールにしたがって無限に生成したランダム単語を保存したり、単語をお気に入り登録したりする機能)で使う。

3-2. statefulなRandomWordsウィジェットをmain.dartに追加する

RandomWordsウィジェットは、Stateクラスを作成する以外にほとんど何もしません。

lib/main.dart

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

3-3. RandomWordsStateクラスのbuildメソッドを追加する

class RandomWordsState extends State {
+ @override
+ Widget build(BuildContext context) {
+   final wordPair = WordPair.random();
+   return Text(wordPair.asPascalCase);
+ }
}

3-4. MyAppから単語生成の部分のコードを取り除いて、statefulなRandomWordsウィジェットを使うようにする

lib/main.dart

class MyApp extends StatelessWidget { 
  @override 
  Widget build(BuildContext context) { 
-   final wordPair = WordPair.random(); 
    return MaterialApp( 
      title: 'Welcome to Flutter', 
      home: Scaffold( 
        title: Text('Welcome to Flutter'), 
        ... 
        body: Center( 
-         child: Text(wordPair.asPascalCase), 
+         child: RandomWords(), 
        ),
      ), 
    );
  } 
}

hot reload⚡️してもsimulatorのアプリはstep2と変わらないことを確認します。

Step 4: Create an infinite scrolling ListView

RandomWordsStateを修正して、単語リストを生成・表示する機能を追加する。
リストにListViewウィジェットを使い、ListViewのビルダーファクトリコンストラクターを使用すると、オンデマンドで遅延してリストビューを作成できるらしい。

4-1. 単語を保存する_suggestionsリストとフォントサイズを大きくする_biggerFont変数をRandomWordsStateクラスに追加する。

lib/main.dart

class RandomWordsState extends State {
+  final _suggestions = [];
+  final _biggerFont = const TextStyle(fontSize: 18.0);
  // ···
}

Unlike Java, Dart doesn’t have the keywords public, protected, and private. If an identifier starts with an underscore (_), it’s private to its library. For details, see Libraries and visibility.

「_」をつけると、dartではprivateになるらしい。

次に、RandomWordsStateクラスに単語リストを表示するListViewをbuildするbuildSuggestions()メソッドを作る。

4-2and4-3. RandomWordsStateクラスに_buildSuggestions(),_buildRow()を追加する

lib/main.dart

Widget _buildSuggestions() {
  return ListView.builder(
      padding: const EdgeInsets.all(16.0),
      itemBuilder: /*1*/ (context, i) {
        if (i.isOdd) return Divider(); /*2*/

        final index = i ~/ 2; /*3*/
        if (index >= _suggestions.length) {
          _suggestions.addAll(generateWordPairs().take(10)); /*4*/
        }
        return _buildRow(_suggestions[index]);
      }
    );
}
Widget _buildRow(WordPair pair) {
  return ListTile(
    title: Text(
      pair.asPascalCase,
      style: _biggerFont,
    ),
  );
}
  • /*1*/
    itemBuilderは単語が提案されるたびにコールバックされ、
    偶数行で、その単語をListTileの行に追加する。
    奇数(isOdd)行では、視覚的に分離するための1pxのDividerウィジェットを追加する。
  • /*4*/
    もし単語リスト_suggestionsの単語の数が上限に達したら、さらに10コの単語を生成しリストに追加する。

4-4. RandomWordsStateクラスbuild()メソッドで_buildSuggestions()を使うようにする。

lib/main.dart

@override
Widget build(BuildContext context) {
+  return Scaffold(
+    appBar: AppBar(
+      title: Text('Startup Name Generator'),
+    ),
+    body: _buildSuggestions(),
+  );
}

4-5. MyAppクラスのbuild()メソッドのtitleを変更し、RandomWordsウィジェットをhome直下に移動させる

lib/main.dart

class MyApp extends StatelessWidget {            
  @override            
  Widget build(BuildContext context) {         
    return MaterialApp(                        
      title: 'Startup Name Generator',            
      home: RandomWords(),                       
    );            
  }
}

 

最後に

つぎはPart2で、スクロールとお気に入り登録機能を追加します!がんばりまーす🙌

最近よくみるFlutterでHello Worldしてみる

 

外出自粛GW暇ですねー、なのでFlutter触ってみることにしました💡
フラッターて読むんですかね、フルッターてずっと読んでました。

参考:
https://flutter.dev/docs/get-started/install/macos
https://apps-gcp.com/cloud-pub-sub-dead-letter-topic/

環境構築

入れるものがまあまあ多い印象ですが、思ったよりはすぐできました。

私の環境

  • macOS Catalina 10.15.4
  • Xcodeは古いのは入ってた(今回バージョン最新にしました)
  • Android Studioは入ってない

したこと

https://flutter.dev/docs/get-started/install/macos
ほぼ、↑の通りにしました。英語は優しいので導入しやすかったです。

  • Flutter SDKの導入
  • Xcodeを最新の11にupdate
  • iOS Simulatorのset up
  • Android Studioのインストール
  • Android Emulatorのset up ←ちゃんとできてないかも…
  • VSCode ←AndroidStudioがあればコードかけるけど念のため入れた

 

Flutter SDKの導入

GitからFlutterSDKをゲット
git clone https://github.com/flutter/flutter.git -b stable
私はbashを使っているので、~/.bash_profileを編集して、flutterコマンドのパスを通す。(source 忘れないように!)

確認してみる。

$ flutter --version
Flutter 1.12.13+hotfix.9 • channel stable • git://github.com/flutter/flutter.git
Framework • revision f139b11009 (5 weeks ago) • 2020-03-30 13:57:30 -0700
Engine • revision af51afceb8
Tools • Dart 2.7.2
...
Xcodeのアップデート

itunesから最新Xcodeにアップデートして、以下のコマンドでrunしてlisenceに同意する。

$ sudo xcode-select --switch /Applications/Xcode.app/Contents/Developer
Password:
$ sudo xcodebuild -runFirstLaunch


You have not agreed to the Xcode license agreements. You must agree to both license agreements below in order to use Xcode.

Hit the Return key to view the license agreements at '/Applications/Xcode.app/Contents/Resources/English.lproj/License.rtf'

Xcode and Apple SDKs Agreement

PLEASE SCROLL DOWN AND READ ALL OF THE FOLLOWING TERMS AND CONDITIONS CAREFULLY BEFORE USING THE APPLE SOFTWARE OR APPLE SERVICES.  THIS IS A LEGAL AGREEMENT BETWEEN YOU AND APPLE.  IF YOU AGREE TO BE BOUND BY ALL OF THE TERMS AND CONDITIONS, CLICK THE “AGREE” BUTTON.  BY CLICKING “AGREE” OR BY DOWNLOADING, USING OR COPYING ANY PART OF THIS APPLE SOFTWARE OR USING ANY PART OF THE APPLE SERVICES, YOU ARE AGREEING ON YOUR OWN BEHALF AND/OR ON BEH
...

By typing 'agree' you are agreeing to the terms of the software license agreements. Type 'print' to print them or anything else to cancel, [agree, print, cancel] agree

You can view the license agreements in Xcode's About Box, or at /Applications/Xcode.app/Contents/Resources/English.lproj/License.rtf

Install Started
1%.........20.........40.........60.........80.........Install Succeeded
iOS Simulatorのセットアップ

以下コマンドでiOS Simulatorを開く
open -a Simulator
File > Open Device より適当なデバイスを選んで、開いて確認してみる。

Flutter アプリを作成してみる

flutter runをすると、さっき開いていたiOS Simulatorに、作成したmy_app_flutterが開きました。

$ flutter create my_app_flutter
$ cd my_app_flutter
$ flutter run

Launching lib/main.dart on iPhone 11 Pro in debug mode...
Running Xcode build...

 ├─Assembling Flutter resources...                           9.0s
 └─Compiling, linking and signing...                         6.3s
Xcode build done.                                           21.8s
Syncing files to device iPhone 11 Pro...
 5,738ms (!)

🔥  To hot reload changes while running, press "r". To hot restart (and rebuild state), press "R".
An Observatory debugger and profiler on iPhone 11 Pro is available at: http://127.0.0.1:61543/7ohrboNLAIo=/
For a more detailed help message, press "h". To detach, press "d"; to quit, press "q".

「Hello world」してみる

Editorは、Android Studioを使いました。

my_app_flutter/lib/main.dart

import 'package:flutter/material.dart';

void main() {
 runApp(App());
}

class App extends StatelessWidget {
 @override
 Widget build(BuildContext context) {
   return MaterialApp(
     home: Scaffold(
       body: Center(child: Text("hello world")),
     ),
   );
 }
}

上記に書き換えて、既にiOS Simulatorを開いている状態では、
⚡️マークのhot reloadをすると、runしなくても更新してくるようです。

できたー!

 

最後に

Android Emulatorもいれたので、試したかったんですがMacユーザのためAndroidの操作法がわからず🤔
と思ったら、AndroidでもEmulatorできましたー!(ヘッダーとフッターは追加しました。)

次は何かできるアプリを作成したいです!!!