【Flutter】Riverpodを使いUIとロジック分離した中規模アプリ開発を始めよう(導入編)

2021-11-06

はじめに

過去の記事でProvider Patternの記事を書いたことがありました。

Flutterなどでよく使われるデザインパターンの一つと理解しています。 有名所は、Atomic Desigh ,Provider、BLoC、Reduex(Reactでの利用が有名) これらは、必要に応じて今後も勉強していきたいなと思っているところです。

さて、今回紹介するのはそんなProvider Patternを実装するのに利用していたパッケージを改善した別のパッケージがありました。 先日、晴れてVersion 1.0.0が公開されたということで触ってみましたというのが今回の趣旨です。

実態は、Hello Worldを動かすだけなのですがFlutterのバージョンが古いとかその前段階の話がメインになります。 バージョンが古いとか色々難癖つけられて、動かすまでに結構エラーを踏み抜いたので、今後始める方の参考になれば良いなぁと思っています。

riverpodの導入。

Riverpod

主には、状態管理と依存関係を整理するためのライブラリになります。 私の理解は浅いのですが、UIと機能実装部分を分離したりするのに使うのが便利です。 小規模開発なら問題ないですが、中規模開発となると効果を発揮する印象をもっています。

大規模開発では、BLoC Patternを用いるほうが良いと聞いています。 適材適所で使い所を分けるのが良いようですね。

Usage example: Hello world

Getting startedに沿って実行していきましょう。 package.yamlに以下を追加して、

flutter_riverpod:^1.0.0
flutter pub get 

を実行しておきましょう。

インストールが完了していればlib/main.dartをExampleの内容を愚直に実行してみましょう。

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

// We create a "provider", which will store a value (here "Hello world").
// By using a provider, this allows us to mock/override the value exposed.
final helloWorldProvider = Provider((_) => 'Hello world');

void main() {
  runApp(
    // For widgets to be able to read providers, we need to wrap the entire
    // application in a "ProviderScope" widget.
    // This is where the state of our providers will be stored.
    ProviderScope(
      child: MyApp(),
    ),
  );
}

// Extend ConsumerWidget instead of StatelessWidget, which is exposed by Riverpod
class MyApp extends ConsumerWidget {
  @override
  Widget build(BuildContext context, WidgetRef ref) {
    final String value = ref.watch(helloWorldProvider);

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

main.dartを書き換えたら実行します。

flutter run

WidgetRefが見つからないって怒られるとき

Pub.dev flutter_riverpod 1.0.0 英語もちゃんと読まず、Installingにある

flutter pub add flutter_riverpod

だけを実行してしまったうっかりさんだとこんなエラーが出ると思います。

Using hardware rendering with device sdk gphone x86. If you notice graphics artifacts, consider enabling software rendering with
"--enable-software-rendering".
Launching lib\main.dart on sdk gphone x86 in debug mode...
lib/main.dart:22:38: Error: Type 'WidgetRef' not found.
 Widget build(BuildContext context, WidgetRef ref) {
                                    ^^^^^^^^^
lib/main.dart:22:38: Error: 'WidgetRef' isn't a type.
 Widget build(BuildContext context, WidgetRef ref) {
                                    ^^^^^^^^^

FAILURE: Build failed with an exception.

* Where:
Script 'C:\src\flutter\packages\flutter_tools\gradle\flutter.gradle' line: 1035

* What went wrong:
Execution failed for task ':app:compileFlutterBuildDebug'.
> Process 'command 'C:\src\flutter\bin\flutter.bat'' finished with non-zero exit value 1

* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output. Run with --scan to get full insights.       

* Get more help at https://help.gradle.org

BUILD FAILED in 16s

pub get で追加すると、flutter_riverpodが古いものが入ってきますので上記のようなエラーが発生します。 そのため、pubspec.yamlを書き換えていきましょう。

dependencies:
  flutter:
    sdk: flutter

  # The following adds the Cupertino Icons font to your application.
  # Use with the CupertinoIcons class for iOS style icons.
  cupertino_icons: ^1.0.2
  flutter_riverpod: ^0.14.0+3

flutter_rriverpodを下記のように書き換えます。

  flutter_riverpod: ^1.0.0
flutter pub get

これで更新しておわります。ちゃんと読もうな。

which requires SDK version >=2.14.0 <3.0.0, version solving failed.

flutter pub get 

さて、上のコマンドを実行するときに別のエラーが出てきました。 どうにもFlutterのSDKが古いらしく、アップデートが必要とのことです。とりあえず勧めていきましょう。

詳細なエラー内容としてはこちらです。

The current Dart SDK version is 2.13.1.

Because camera_flutter depends on flutter_riverpod >=1.0.0 which requires SDK version >=2.14.0 <3.0.0, version solving failed.
Running "flutter pub get" in camera_flutter...                          
pub get failed (1; Because camera_flutter depends on flutter_riverpod >=1.0.0 which requires SDK version >=2.14.0 <3.0.0, version solving failed.)
SDK Versionアップ対応の実施(flutter upgrade –force)

SDK version古いからUpdateしてくれって怒られたので、以下の手順でUpdateしていきます。 まずはflutterのバージョンアップ状況を確認します。

flutter channel stable

このような画面が出たら、バージョンアップできる状態です。

  ╔════════════════════════════════════════════════════════════════════════════╗
  ║ A new version of Flutter is available!                                     ║
  ║                                                                            ║
  ║ To update to the latest version, run "flutter upgrade".                    ║
  ╚════════════════════════════════════════════════════════════════════════════╝

Switching to flutter channel 'stable'...
git: Your branch and 'origin/stable' have diverged,
git: and have 13 and 1849 different commits each, respectively.
git:   (use "git pull" to merge the remote branch into yours)
git: Already on 'stable'
Successfully switched to flutter channel 'stable'.
To ensure that you're on the latest build from this channel, run 'flutter upgrade'

flutter upgradeを使ってアップデートしましょう。

flutter upgrade

もし以下のようなエラーが出る場合は、–forceを付けて実行します。 flutter本体をどこかのタイミングでいじってしまったのが原因ですかね。

Your flutter checkout has local changes that would be erased by upgrading. If you want to keep these changes, it is recommended that you stash them via
"git stash" or else commit the changes to a local branch. If it is okay to remove local changes, then re-run this command with "--force".
flutter upgrade --force

アップデートが完了したらflutter doctorが実行されます。 私のケースではAndroidのtoolchainで失敗しているので追加で対応していきます。

Android toolchainのアップデートが失敗する件
flutter upgrade --force

を実行すると最後にFlutter doctorが実行されます。

実行結果としては、FlutterはUpdate成功していますが、どうにもAndroid toolschainでコケているようです。原因を見ていきます。

ログを丸っと貼り付けておきます。

Upgrading Flutter to 2.5.3 from 2.2.1 in C:\src\flutter...
Checking Dart SDK version...
Downloading Dart SDK from Flutter engine d3ea636dc5d16b56819f3266241e1f708979c233...
Expanding downloaded archive...
Building flutter tool...
Running pub upgrade...

Upgrading engine...
Downloading android-arm-profile/windows-x64 tools...               460ms
Downloading android-arm-release/windows-x64 tools...               297ms
Downloading android-arm64-profile/windows-x64 tools...             365ms
(略)
Running flutter doctor...
Doctor summary (to see all details, run flutter doctor -v):
[√] Flutter (Channel stable, 2.5.3, on Microsoft Windows [Version 10.0.19042.1052], locale ja-JP)
[!] Android toolchain - develop for Android devices (Android SDK version 30.0.3)
    X cmdline-tools component is missing
      Run `path/to/sdkmanager --install "cmdline-tools;latest"`
      See https://developer.android.com/studio/command-line for more details.
    X Android license status unknown.
      Run `flutter doctor --android-licenses` to accept the SDK licenses.
      See https://flutter.dev/docs/get-started/install/windows#android-setup for more details.
[√] Chrome - develop for the web
[√] Android Studio (version 4.1)
[√] VS Code (version 1.61.2)
[√] VS Code, 64-bit edition
[√] Connected device (3 available)

! Doctor found issues in 1 category.

追加でAndroidに絞って確認していきます。

flutter doctor --android-licenses
Android sdkmanager not found. Update to the latest Android SDK and ensure that the cmdline-tools are installed to resolve this.

Android sdkmanagerが無いって怒られているようです。

Android sdkmanager not found. に対する解決策

Android StudioからSDK Mangerを開きます。 Android SDKのSDK Toolsを開きます。 Hide Obsolete Packagesのチェックを外して、「Android SDK Tools」をインストールします。

これで解決します。

ググっても見ると、Android StudioでAndroid SDK toolsのパッケージ名が、Android-SDK command line toolsに変更されたのが原因のようです。 その関係で古いパッケージが削除された(名前が変更されてなくなってしまった)というようなところですかね。真偽はわからないですが、サラッと調べたらそう書いてました。

インストール後、再度下記のコマンドを実行し通っていることが確認します。

flutter doctor --android-licenses
All SDK package licenses accepted.======] 100% Computing updates..

動いてそうなので追加確認しておきます。 flutter doctorを再度実行すると全てにチェックが付いてるはずです。

flutter doctor
Doctor summary (to see all details, run flutter doctor -v):
[√] Flutter (Channel stable, 2.5.3, on Microsoft Windows [Version 10.0.19042.1052], locale ja-JP)
[√] Android toolchain - develop for Android devices (Android SDK version 30.0.3)
[√] Chrome - develop for the web
[√] Android Studio (version 4.1)
[√] VS Code (version 1.61.2)
[√] VS Code, 64-bit edition
[√] Connected device (3 available)

これにてアップデートは完了です。お疲れさまでした。

Usage example: Hello world の実行結果

これでやっとRiverpodが動かせる状態になりました。

flutter run

VSCodeのSnippetを導入しよう

Flutter Riverpod Snippets

開発時には役立つSnippetを入れておくといいでしょう。

まとめ

よくあるエラー解決集になってしまいましたが、Riverpodを動かすところまでできました。 Providerのアナグラムになっているようで、同一作者ならではなお遊び心がありますね。

環境は整ったので明日以降時間があるときにFlutterアプリを作っていきましょう。