もっぺんプログラミング(´・ω・`)

もっぺん頑張って副業プログラマを目指してます。

100日後にFlutter生活:12日目:6章でとりあえず画面が出るまで

6章のサンプルコードで、とりあえずトップ画面が出るところまでたどり着けた…

僕の知識不足に、本の説明不足感もあいまって なかなかの難易度やった…

Flutter モバイルアプリ開発バイブル

やったこと。

Git clone でソースコードを取得

↓こんなん

> git clone https://github.com/AwaseFlutter/dart_ffi_example.git

GitHubリポジトリ GitHub - AwaseFlutter/dart_ffi_example: 『Flutter モバイルアプリ開発バイブル』の「付録 Flutter 1.9」における実装サンプルです。

flutter pod get で、必要なパッケージ取得

ソースを取得したら、Sampleフォルダに移動して、必要なパッケージを取得

> cd Sample
> flutter pub get
ソースコードの警告を修正

Eventクラスのコンストラクタで警告が出てたので修正。

date が必須になってるのに、代入文が書かれてなかった。
こ、このサンプルコード、動くのかな?ドキドキ…

↓この一番下の行を追記しました。

  Event({
    @required this.id,
    @required this.title,
    @required this.description,
    @required this.date,
    @required this.imageUrl,
  })  : assert(id != null),
        assert(title != null),
        assert(description != null),
        assert(date != null),
        assert(imageUrl != null);

  static Event fromJson(Map<String, dynamic> json) {
    return Event(
      id: json['id'],
      title: json['title'],
      date: json['date'],
iOSのビルドが終わらない問題

Xcodeで、ドメインをユニークなものに変更しないとダメだった。 忘れてました。

ので、Sample/ios 以下をXCodeで開いて、Runnerのドメイン名を変更

f:id:momoizo:20210125005315p:plain

Firebaseにプロジェクト登録

↓以下の手順に従って、プロジェクト登録
 初めての人は、Firebaseの利用登録からかな?

Flutter アプリに Firebase を追加する

手順中に、GoogleService-info.list をダウンロードする場面が出てくるので
ダウンロードして、XCodeを開いて、Runnerディレクトリの直下に追加。
XCodeで実施しないとダメな模様)

__FIRAPP_DEFAULT does not exist. にも対応

コンソールに以下のメッセージが出てて、気になったので調べて対応。

6.23.0 - [Firebase/Core][I-COR000004] App with name __FIRAPP_DEFAULT does not exist.
Configured the default Firebase app __FIRAPP_DEFAULT.

Objective-C でプロジェクトが生成されてたので以下を修正

※ファイルは、Sample/ios/Runner/Runner にある。

AppDelegate.h

#import <Flutter/Flutter.h>
#import <UIKit/UIKit.h>

@import Firebase;

@interface AppDelegate : FlutterAppDelegate

@end

AppDelegate.m

#include "AppDelegate.h"
#include "GeneratedPluginRegistrant.h"

@implementation AppDelegate

- (BOOL)application:(UIApplication *)application
    didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
  [FIRApp configure];
  [GeneratedPluginRegistrant registerWithRegistry:self];
  // Override point for customization after application launch.
  return [super application:application didFinishLaunchingWithOptions:launchOptions];
}

@end

参考: FlutterでFirebaseを利用するために[FIRApp configure];を追加 | by Kaoru Mori | Medium

Unhandled Exception: に対応

デバッグ起動すると、まだ以下が出るので調べて対応。

[VERBOSE-2:ui_dart_state.cc(177)] Unhandled Exception: ServicesBinding.defaultBinaryMessenger was accessed before the binding was initialized.
If you're running an application and need to access the binary messenger before `runApp()` has been called (for example, during plugin initialization), then you need to explicitly call the `WidgetsFlutterBinding.ensureInitialized()` first.
If you're running a test, you can call the `TestWidgetsFlutterBinding.ensureInitialized()` as the first line in your test's `main()` method to initialize the binding.
#0      defaultBinaryMessenger.<anonymous closure>
package:flutter/…/services/binary_messenger.dart:92
#1      defaultBinaryMessenger
package:flutter/…/services/binary_messenger.dart:105
#2      MethodChannel.binaryMessenger
package:flutter/…/services/platform_channel.dart:143
#3      MethodChannel.setMethodCallHandler
package:flutter/…/services/platform_channel.dart:379
#4      new FirebaseAuth._ (package:firebase_auth/src/firebase_aut<…>

エラーメッセージに、main メソッドで初期化処理を呼ぶコードを追加っと

void main() {
  WidgetsFlutterBinding.ensureInitialized();

これで、一応、トップ画面が出るようになりました!

けど、ボタンを押したらアプリが落ちる… エラーメッセージを何も出さずに終わるから、ここからさらに調査かな〜

(´・ω・`)サンプルコードの難易度高すぎるぅ

100日後にFlutter生活:11日目:4, 5 流し読みつつ 6章のビルド待ち…

Flutterと並行して、動画編集を勉強しはじめてみたら、更新が止まってしまった…(ダメ) まさに、2頭を追うもの1頭も…パターン。

頑張っていきたい。

当初、Premiere Elements で頑張ってみたけど挫折。 その後、Filmora X に変更。

プリセットでいろんなエフェクト入っているし、使いやすくて楽しい〜。

Premiere Elements は、もったいなかったけど、挫折したら意味無し… 動画編集も頑張ってみよう。

さて、Flutterの方は、更新が途絶えたけど一応少しずつ進んでました。 本読んだだけだけどw

4章の状態遷移については、ざっと流してみたけど「ふーん」という感想。 作ってみないと、良くわからん… とはいえ、MVC あたりで止まってる身としては、ReduxやBLocのシーケンスの比較は面白かったかも。 いつかは、ちゃんと理解したい。

5章のライブラリについても、開発に慣れてきた時に思い出せればいいかな、という内容かも。 まだ、アプリも真っ当に作れないのに、ライブラリを作る余力なしw とはいえ、いつかは分かるようになりたい。

ということで、6章のサンプルアプリが理解出来る方を優先してみました。

それにしても、4章以降、説明が一足とびな感じで、開発経験が無いと理解が結構厳しそう… 6章のサンプルアプリも、コード全て書かれてないし、完成したアプリのスクショは無いし GitHubでソース取得して、やってみてね。だし、なかなか難易度高いw

GitHubでソース取得したら

flutter pub get

を忘れずに!

100日後にFlutter生活:10日目:3章読了(こんどこそ)

昨日、3章読了と書いたものの、やはり最後の InheritedWidget の理解不足が気になったので、再読&写経

やっぱり、実際にコードを書いて動かしてみないと、良くわからないね。

最近のプログラミングで混乱しやすいのは、変数のバインドかなぁ。 UI系のフレームワークで良く出るけど、変数と画面パーツの属性を紐付けておくと、変数値が変更された時に、勝手に画面パーツの属性値も変えてくれるやつね。 逆もあるみたい。

全自動で便利すぎて、ひと昔前のエンジニア的には、裏で何が起こってるの?!そこまで自動なの?!と、何度見ても驚いてしまう。

沢山書けば、馴染んでくるかな?

InheritedWidget クラスのイメージも、なんとなく分かったので、明日こそ本当に4章に行きます!

Flutter モバイルアプリ開発バイブル

100日後にFlutter生活:9日目:3章読了

例によって、Flutter モバイルアプリ開発バイブルを読み進めています。 ついに3章読了・・・

Flutter モバイルアプリ開発バイブル

3章最後の、InheritedWidget も実装してみて、コードを確認したかったけど 今日は眠すぎて無理や・・・(ダメ)

パフォーマンス・チューニング目的ではあったけど、以下を勉強できてよかった。

  • 上位Widgetから下位Widgetを参照する方法(Keyを使う)
  • 下位Widgetから上位Widgetを参照する方法(BuildContextから辿れる)
  • キャッシュ化、定数化の書き方。(キャッシュ化は、リビルドのタイミングが分からなかったが・・・)
  • InheritedWidget を使った方法

明日、もう一回整理して4章に行こう・・・

100日後にFlutter生活:8日目:パフォーマンス劣化サンプルを読む

引き続き、Flutter モバイルアプリ開発バイブル の3章の途中。

Flutterは、Widgetをツリー構造にして画面を構築する特性上、下位まで依存関係を持つような作りにしてしまうと ほんの僅かなステータス変更でも、膨大な再描画になるよ。

というサンプルぽい。

サンプルの意図と異なるけど、このコードを写経していく中で、ウィジェットの属性をStateオブジェクトから参照する方法を覚えた。

↓こういうやつです。一番最後の行で、「widget. 」とすることで、Stateと紐付いているWidgetを参照できるぽい。ほほー。

class AnotherWidget extends StatefulWidget {
  final ImportantData importantData;

  AnotherWidget({Key key, @required this.importantData})
    : assert(importantData != null),
      super(key: key);
  
  @override
  _AnotherWidgetState createState() => _AnotherWidgetState();
}

class _AnotherWidgetState extends State<AnotherWidget>{
  ImportantData get _importantData => widget.importantData;

会社の方は、プロジェクトキックオフに向けてバタバタしたこともあり、めちゃ眠たいw

サンプルコード読んでても、全く頭に入ってこないので寝ますw

100日後にFlutter生活:7日目:アニメーションでつまずく。(スルー力発動)

引き続き、Flutterモバイルアプリ開発バイブルを読み進めてます。

が… アニメーションしない…

コードは、なんどか確認したけど、原因わからず… 一晩寝たら、何かわかるかも?何故か直るかも?

と思ったけど、解決せず。

今の実力では、問題解決ができないということやな…

とりあえず、分からない部分はスルーして進みます。

import 'package:flutter/animation.dart';
import 'package:flutter/material.dart';

class LogoAnimationScreen extends StatefulWidget{
  @override 
  _LogoAnimationState createState() => _LogoAnimationState();
}

class _LogoAnimationState extends State<LogoAnimationScreen> with SingleTickerProviderStateMixin {
  //追加
  AnimationController controller;
  Animation<double> animation;

  @override
  void initState() {
    super.initState();
    controller = AnimationController(duration: Duration(seconds: 2), vsync: this)
      ..addListener(() {
        setState(() {});
      });
    animation = Tween<double>(begin: 10, end: 300).animate(controller);
  }

  @override
  void dispose() {
    controller.dispose();
    super.dispose();
  }

  @override 
  Widget build(BuildContext context) => Scaffold(
    appBar: AppBar(
      title: Text('あにめ')
    ),
    body: Center(
      child: Container(
        margin: EdgeInsets.symmetric(vertical: 10),
        height: animation.value,
        width: animation.value,
        child: FlutterLogo(),
      )
    )
  );
}

100日後にFlutter生活:6日目:Widgetをまたぐ状態管理

今日も、「Flutter モバイルアプリ開発バイブル」3章を読み進める。

休日出勤してたので、ちょっと読んだだけ。 なんだけど、電卓アプリのサンプルで感じた疑問が解消された〜。

3日目あたりに作った電卓アプリでは、ボタンのイベントで呼び出すメソッドを渡せなくて、Staticなメソッドを使ったり、非同期イベントを使ってたけど、もっとシンプルに出来ることが分かった。

なるほどね〜

明日は、アニメーションにトライ。

まだ、コントロールを自由にレイアウト出来ないから、画面設計がイマイチ… 果たして、いつになったらレイアウトも操れるようになるのやら。