サンプルリポジトリのリンク
flavor.dart
のコード全容はこちらのリンクから、GitHubリポジトリにて確認できます。
Flavorを使うと、開発環境・テスト環境・本番環境というようにアプリの環境を変化させることが可能です。
開発環境と本番環境で異なる文字列を表示させたかったり、安全のため異なるデータベースを使いたいことは多々あるので、各Storeで公開するアプリにとってはほぼ必須と言っても良い機能ではないでしょうか。
当書籍ではRiverpodに主眼をおいているため、Flavorの詳細やiOS, Androidでの設定は割愛いたします。
なぜProviderか
Flavorはアプリビルド時や起動時に指定するものであり、基本的にアプリ内で変えるものではありません。
なので、変化する状態を持たない、一番基本的な「Provider」を使用します。
Flavorを指定するオプションを追加
まず、FlutterアプリにFlavor(環境)を伝えるには、 dart-define
オプションを使って指定します。
以下のように build or run の後に --dart-define=FLAVOR=
と書き、任意の環境文字列で指定します。
$ flutter build --dart-define=FLAVOR=development
$ flutter run --dart-define=FLAVOR=development
Flavorの定義
Flavor自体は enum で表現しましょう。
ここでは、3種類のFlavorを定義しましたが、Flavorの数と名前は好みのものを設定ください。
(他の方の記事を読むと、 develop
, qa
, prod
などの文字列を見かけますね)
enum Flavor {
development,
staging,
production,
}
// 拡張して、文字列を返すGetterを用意しておくと、何かと便利です。
extension FlavorExt on Flavor {
String get key => describeEnum(this);
}
Providerの作成
続いて、Flavorを入れるためのProviderを宣言します。
final flavorProvider = Provider<Flavor>((ref) => throw UnimplementedError());
後ほど必ず値を入れるため、初期値では throw UnimplementedError()
のエラーを投げています。
初期値がFlavorではないため、 <Flavor>のように型の明示を忘れないようにしましょう。
明示しなければ、 Provider<Never>
と推論されてしまいます。
main関数でFlavorを受け取り、ProviderScopeに渡す
では、 main関数でFlavorを受け取り、 flavorProvider
の値を上書きしましょう。
void main() {
// `runApp` 関数完了前に何か処理を行いたいときに実行必須の関数です。
WidgetsFlutterBinding.ensureInitialized();
// ビルド時に指定したFlavorを取得
final flavorString = const String.fromEnvironment('FLAVOR');
// enumから `flavorString` と一致する Flavor を取得
final flavor = Flavor.values.firstWhere((e) => e.key == flavorString);
runApp(
ProviderScope(
overrides: [
// flavorProviderの値に `flavor` を入れる
flavorProvider.overrideWithValue(flavor),
],
child: App(),
),
);
}
String.fromEnvironment('FLAVOR')
と書くことで、ビルド時に --dart-define=FLAVOR=xxx
で指定したFlavorの文字列を取得できます。
あとは、その文字列からFlavorを特定し、 ProviderScopeの overridesで flavorProvider
の値を上書きすれば完了です。
flavorProvider
を読み込むことで、アプリのどこからでもFlavorが取得できるようになりました🎉
参考リンク
Creating flavors for Flutter - Flutter