100日後にFlutter生活:12日目:6章でとりあえず画面が出るまで
6章のサンプルコードで、とりあえずトップ画面が出るところまでたどり着けた…
僕の知識不足に、本の説明不足感もあいまって なかなかの難易度やった…
やったこと。
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のドメイン名を変更
Firebaseにプロジェクト登録
↓以下の手順に従って、プロジェクト登録
初めての人は、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章に行きます!
100日後にFlutter生活:9日目:3章読了
例によって、Flutter モバイルアプリ開発バイブルを読み進めています。 ついに3章読了・・・
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(), ) ) ); }