Flutter + flutter_hooksで始めるUI分離パターン

2022-06-07-flutter-flutter-hooksで始めるui分離パターン-7ffda744.webp
目次

はじめに

Flutterを始めました。お前何度始めるんだという意見も最もです。 3度目ぐらいの再入門でびっくりしたのはFlutter君、いつの間にかVer3.00になっていましたね。

RustやGoやPython、VBA、Office Script、C/C++、Rubyと用途に合わせて色んな言語に触れてあれ?どれがどの書き方だっけとなる中、Flutterは手軽さもありつつ、やはりUIと処理部分が一緒くたに書かれているのが気になります。

アルバイトで少し大きめのソフトを書くことになりそうなので、 リハビリも兼ねて備えておこうと思い記事に残します。

Riverpod

リアクティブ・キャッシングとデータバインディングを実現するフレームワーク Riverpod

プロバイダという概念を導入して、FlutterのStateをオーバラップしていい感じに組み合わせ安くしたり、テスト機能を追加したりするパッケージ。

導入

pubspec.yamlに追加する

environment:
  sdk: ">=2.12.0 <3.0.0"
  flutter: ">=2.0.0"

dependencies:
  flutter:
    sdk: flutter
  flutter_hooks: ^0.18.0
  hooks_riverpod: ^2.0.0-dev.9
flutter pub get

準備完了。

Hello world

まずは挨拶。ほんと挨拶は大切なんよ。 普段話さない人でもとりあえず元気に挨拶しておけば後ろ指さされない。

新人の頃に「お前、まじで新人として可愛げはないが、挨拶だけは一番元気なので憎めない」と言われたこともあります。そんな事思っても口に出すなと思いましたが……挨拶してなければ憎まれていたんでしょう。クワバラクワバラ。

main.dartを公式チュートリアルのサンプルのように動かします。

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

// 値(ここでは "Hello world")を格納する「プロバイダ」を作成します。
// プロバイダを使うことで値のモックやオーバーライドが可能になります。
final helloWorldProvider = Provider((_) => 'Hello');

void main() {
  runApp(
    // プロバイダをウィジェットで利用するには、アプリ全体を
    // `ProviderScope` ウィジェットで囲む必要があります。
    // ここに各プロバイダのステート(状態)・値が格納されていきます。
    ProviderScope(
      child: MyApp(),
    ),
  );
}

// flutter_hooks 併用時は hooks_riverpod の HookConsumerWidget を継承します。
class MyApp extends HookConsumerWidget {
  @override
  Widget build(BuildContext context, WidgetRef ref) {
    final String value = ref.watch(helloWorldProvider);

    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(title: const Text('Example')),
        body: Center(
          child: Text(value),
        ),
      ),
    );
  }
}

実行するとこうなります。

Providerを追加する

Global変数としてProviderを追加するのが基本です。 cityproviderとcountrProvidorを追加しました。 使う際にはそれをMyAppの中で読み出しています。

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

// 値(ここでは "Hello world")を格納する「プロバイダ」を作成します。
// プロバイダを使うことで値のモックやオーバーライドが可能になります。
final helloWorldProvider = Provider((_) => 'Hello');
final cityProvider = Provider((ref) => 'London');
final countryProvider = Provider((ref) => 'England');

void main() {
  runApp(
    // プロバイダをウィジェットで利用するには、アプリ全体を
    // `ProviderScope` ウィジェットで囲む必要があります。
    // ここに各プロバイダのステート(状態)・値が格納されていきます。
    ProviderScope(
      child: MyApp(),
    ),
  );
}

// flutter_hooks 併用時は hooks_riverpod の HookConsumerWidget を継承します。
class MyApp extends HookConsumerWidget {
  @override
  Widget build(BuildContext context, WidgetRef ref) {
    final String value = ref.watch(helloWorldProvider);
    final String value1 = ref.watch(cityProvider);
    final String value2 = ref.watch(countryProvider);

    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(title: const Text('Example')),
        body:
            Column(children: <Widget>[Text(value), Text(value1), Text(value2)]),
      ),
    );
  }
}

変数の値を更新する場合

ボタンが押されるたびにカウンタを更新する場合こうなります。

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

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

void main() {
  runApp(ProviderScope(child: MyApp()));
}

class MyApp extends HookConsumerWidget {
  @override
  Widget build(BuildContext context, WidgetRef ref) {
    final int count = ref.watch(counterProvider);

    return MaterialApp(
      home: Scaffold(
        body: Center(child: Text('$count')),
        floatingActionButton: FloatingActionButton(
          onPressed: () {
            ref.read(counterProvider.notifier).state++;
          },
        ),
      ),
    );
  }
}

まとめ

とりあえずこんなところでどうか。 最近、仕事忙しすぎて朝の7時ぐらいから22時ぐらいまで働いてる… 子供の機嫌が悪くなると家庭内の空気が淀むので、できる限り離業したりしつつですが… 妻も疲れていることでしょう……アルバイトも含め一段落したら旅行に行きたいですね

Related Post

> Flutter + flutter_hooksで始めるUI分離パターン
【Flutter】Riverpodを使いUIとロジック分離した中規模アプリ開発を始めよう(導入編)
> Flutter + flutter_hooksで始めるUI分離パターン
FlutterでProviderパターンを使ってUIとロジックを分離する方法
> Flutter + flutter_hooksで始めるUI分離パターン
FlutterでWebRTCを使ったビデオ通話アプリを試してみる
> Flutter + flutter_hooksで始めるUI分離パターン
Android EmulatorでWebカメラの映像を出力する方法【Flutter】
> Flutter + flutter_hooksで始めるUI分離パターン
Android Emulatorが立ち上がらずに困ったときの対処方法【Android Emulator closed because of an internal error】
> Flutter + flutter_hooksで始めるUI分離パターン
Flutterアプリのインストールができない原因と対策

おすすめの商品

>