Closed8

[2022.11] O: Flutter中級者になる / KR1: 入門書を1冊読む / KR2: Riverpodを使った状態管理ができる / KR3: テストが書ける

ひろとひろと

2022.11.19 更新

O: Flutter中級者になる

KR1: 入門書を1冊読む[50%]

先月に引き続き「現場で使える Flutter開発入門 (Compass Booksシリーズ)」を読み進める

KR2: Riverpodを使った状態管理ができる[0%]

BKR2-1: 色々な状態管理手法のメリット・デメリットを整理し、Riverpodの特徴を言語化する [30%]

BKR2-2: Riverpodを使ったアプリを一つ作る [30%]

KR3: テストが書ける[0%]

BKR3-1: Unit Testを書く[0%]

BKR3-2:Widget Testを書く[100%]

BKR3-3: Integration Testを書く[0%]

ひろとひろと

2022.11.01

Integration Testに使えそうなツール

https://firebase.google.com/products/test-lab?hl=ja

MediaQueryとは

https://zenn.dev/chooyan/articles/3c2691e93f4038
主な役割は画面サイズを取得すること

MediaQueryはInheritedWidgetのサブクラス

Inherited Widgetとは

https://zenn.dev/chooyan/articles/bd8b5990eb210f

「祖先(任意の親)の位置にあるInheritedElementへの参照を、全てのElementが保持している」
ツリーの順序を飛び越えて、祖先のWidgetの持つデータ(アプリ全体の色やフォントなど)を使いたい場合の機能らしい

3つのツリーとは

https://zenn.dev/chooyan/articles/77a2ba6b02dd4f

  • Widgetツリー
    • Immutableなオブジェクト
    • Widget.createElementでペアとなるElementを生成
  • Elementツリー
    • 親と子への参照を持つ
    • BuildContextのimplements
  • RenderObjectツリー
    • 画面にUIを描画するオブジェクト

インスタンスをなるべく再利用して、レンダリングの高速化を行えるようにしている。

この動画が分かりやすかった
https://youtu.be/996ZgFRENMs


Flutterのアーキテクチャ

https://www.didierboelens.com/2019/09/flutter-internals/
https://zenn.dev/seya/articles/f7ebcd8335eee7

ひろとひろと

2022.11.02

Riverpodの概要

https://github.com/rrousselGit/riverpod
https://riverpod.dev/docs/concepts/providers

providerを進化させた状態管理ツール(同じ作者)
https://github.com/rrousselGit/provider

provider: InheritedWidgetをsimplifyしたもの
riverpod: InheritedWidgetをfrom scratchで作り直したもの

  • providerとriverpodは共通した目的を持っている

    • stateの作成・監視・削除を安全に行いたい
    • Flutterのdevtoolで見えるオブジェクトにしたい
    • Testableにしたい
    • InheritedWidgetsをもっと読みやすくしたい
    • データフローを一方向にしたい
  • riverpodがproviderより優れているところ

    • compile safeなオブジェクトになっているので、runtime exceptionに悩まされない
    • より柔軟な実装が可能になった
      • 同じ型のproviderを複数使える
      • providerのstateが不要になったら自動で削除できる
      • computed stateを使える
      • providerをprivateにできる
    • 非同期なstateを使える?
    • Flutterと独立した実装になっている

InheritedWidgetを一から実装し直したことで、上記の利点を得られるようになった。

Providerの概要

https://github.com/rrousselGit/provider

Riverpod使ってみる

flutter pub add flutter_riverpod
import 'package:flutter_riverpod/flutter_riverpod.dart';

void main() {
  runApp(const ProviderScope(child: MyApp()));
}
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';

final counterProvider = StateProvider((ref) => 0);

class Home extends ConsumerWidget {
  
  Widget build(BuildContext context, WidgetRef ref) {
    return Scaffold(
      appBar: AppBar(title: const Text('Counter example')),
      body: Center(
        // Consumer is a widget that allows you reading providers.
        child: Consumer(
          builder: (context, ref, _) {
            final count = ref.watch(counterProvider);
            return Text('$count');
          },
        ),
      ),
      floatingActionButton: FloatingActionButton(
        // The read method is a utility to read a provider without listening to it
        onPressed: () => ref.read(counterProvider.notifier).state++,
        child: const Icon(Icons.add),
      ),
    );
  }
}

変化

  • 今までStatelessWidgetやStatefullWidgetを継承していたが、ConsumerWidgetになった
  • buildメソッドの引数にWidgetRef型のrefが増えた
  • ref.watch(provider)で状態の監視
  • ref.read(provider.notifier)で状態の読み込み

Riverpodを使うときのアーキテクチャ

https://codewithandrea.com/articles/flutter-app-architecture-riverpod-introduction/

2021.11にriverpod1.0.0がリリースされたから、これ以前の記事・書籍はインターフェースが異なる

https://zenn.dev/riscait/books/flutter-riverpod-practical-introduction/viewer/migrate-to-v1

古い書籍買っちゃったw
https://www.amazon.co.jp/入門-Riverpod-岡花-智貴-ebook/dp/B09D9Q4R2F?encoding=UTF8&qid=&sr=&linkCode=sl1&tag=flt0c-22&linkId=a062e51c70a48671ed2abb66d850323a&language=ja_JP&ref=as_li_ss_tl

後で読む

ひろとひろと

2022.11.04

Dartの気になる文法メモ

https://dart.dev/guides/language/language-tour

継承・抽象クラス・インターフェース・Mixinの違い

finalとconstの違いは「値が固定されるタイミング」

  • const: コンパイル時に値が代入され、それ以降変更できない
  • final: 実行時に値が代入され、それ以降変更できない

Null Safety

https://dart.dev/null-safety

変数がnullを許容しない、のがデフォルトになっている

int? x

のようにするとpythonで言うところのOptionalになる

x!

のようにするとnullを許容しないように変更できる

Generic型も使える

List<Object>

public, protected, privateのようなキーワードがなく、アンダースコアでプライベートな変数・関数を表現する

libraryを部分的にimportする

// Import only foo.
import 'package:lib1/lib1.dart' show foo;

// Import all names EXCEPT foo.
import 'package:lib2/lib2.dart' hide foo;

必要になったらimportするlazy loading

import 'package:greetings/hello.dart' deferred as hello;

Future<void> greet() async {
  await hello.loadLibrary();
  hello.printGreeting();
}
  • 用途
    • webアプリの初期化処理の時間を削減する
    • ABテストでどちらか一方しか実行しないとき
    • optionalなスクリーンやダイアログなどたまにしか使わないライブラリ
ひろとひろと

2022.11.13

「再実装Flutter」という書籍(技術書展で見つけた本)をざっと読んだのでまとめる。

KRと関係ないことばかりやっているな笑

Engine/TaskRunner

マルチスレッドでUIフレームワークを動かす。
なぜなら、画面表示を30fps以上で行う必要があるから。
FlutterのEngine内でスレッドはTaskRunnerと呼ばれていて、4つのTaskRunnerが動いている。

  • Platform
    • メインスレッド
  • UI
    • Dartコードを実行するスレッド
  • Raster
    • 画面描画するスレッド
  • IO
    • 重い処理を行うスレッド

Rasterizeとは

何らかの抽象度の高い形式で記述された画像データを、コンピュータが最終的に出力することのできる画素の集まり(ビットマップ形式/ラスター形式)に変換すること

Layerツリーの実装

RenderTree -> LayerTree -> Engineという流れでデータが送られるらしい

Engine は主に C++で書かれており、Skia という C++のグラフィックライブラリを描画に用いています
LayerTreeはSkiaが理解できるデータ形式になっているということだろうか。
データ形式というよりは描画コマンドを保持しているらしい。

  • PictureLayer
    • 描画コマンドを保持するLayer
  • ContainerLayer
    • 複数のLayerを保持するコンテナの役割を持つLayer
    • TransformLayer, OffsetLayer, ClipRectLayerなど子に特定のエフェクトを作用されるために使用する

RenderObjectの実装

RenderツリーからLayerツリーを生成する

ひろとひろと

2022.11.15

Flutter Architecture Overviewを読む

https://docs.flutter.dev/resources/architectural-overview

Reactive user interfaces

Flutterは「reactive」で「pseudo-declarative UI」なframeworkである

  • 伝統的なUI frameworkの問題点
    • 「状態」とUIとの整合性が取れなくなる
  • MVC的なframeworkの問題点
    • UI elementの作成と更新が同期しずらい
  • Flutter
    • Widgetはimmutableなclassであり、configのような存在
    • WidgetツリーからRenderツリーを生成するので、UI = f(state)という構造が明確であり、状態とUIの分離、更新漏れが起きない.

らしい。

Flutter(Widget Tree) -> Render Tree -> Layout Tree

エンジニアは作りたいUIを設定ファイルのような形で記述すれば良いだけなところが「declarative」なのかな。

なんとなくわかったくらいの感触。

Rendering and layout

Widgetツリーから画面のピクセルまで変換される仕組みについて解説する章

ひろとひろと

2022.11.19

Flutterテストについて調べる

全体像

https://docs.flutter.dev/cookbook/testing
https://zenn.dev/tomofyro/articles/1228cf8f2b02ce

Widget Test

https://docs.flutter.dev/cookbook/testing/widget/introduction

ステップ

Add the flutter_test dependency.
Create a widget to test.
Create a testWidgets test.
Build the widget using the WidgetTester.
Search for the widget using a Finder.
Verify the widget using a Matcher.

サンプルコード
https://github.com/flutter/flutter/tree/master/examples/layers/test
https://github.com/flutter/flutter/blob/master/examples/layers/test/sector_layout_test.dart

このスクラップは2023/01/02にクローズされました