【Flutter】環境変数を利用して効率的な開発環境を構築

対象者

  • Flutterでの環境変数設定方法を学びたいエンジニア
  • 環境ごとに異なる設定を効率的に管理したい開発者
  • 短時間で実践的な知識を身につけたい人

はじめに

アプリ開発の中で、開発環境や本番環境など複数の設定を管理するのは、意外と手間がかかるものです。環境ごとに異なるAPIエンドポイントや機能フラグを適切に切り替えたいけれど、どうすれば効率的に管理できるのか悩んでいませんか?Flavorもいいが、そこまで大規模ではない。そのようなときに役立つのが「環境変数」を使った設定管理です。

この記事では、Flutterで環境変数をどのように設定し、どのように使えばよいのかを、初心者でも分かりやすく解説します。具体的なコード例や実際のコマンドを交えながら、環境変数の基本から応用までを丁寧に説明しますので、プロジェクトにすぐ活かせる実践的な知識を得られます。

Flutterでの環境変数の利用について

環境変数の役割と利点

環境変数は、アプリケーションの動作環境ごとに設定を動的に切り替えるために使用されます。これにより、コードを修正することなく開発・テスト・本番環境で異なる設定を適用することが可能です。Flutterにおいても、環境変数を利用することで、APIエンドポイントやフラグの値を柔軟に管理でき、アプリケーションの運用が効率化されます。

環境変数を使う理由は、コード内に設定をハードコーディングしてしまうと、環境が変わるたびにコードを修正する必要があり、管理が煩雑になるからです。特に、複数の環境でアプリを運用する場合、環境変数を使えば、ビルドプロセスを経ることなく即座に設定を切り替えることができ、エラーの発生も防ぎやすくなります。これにより、環境に依存する設定ミスを防止し、開発のスピードを上げることが可能です。

Flutterでの環境変数の設定方法

Flutterで環境変数を設定する方法としては、主にコマンドラインから設定する方法が一般的です。dart-defineオプションを使用することで、起動時に環境変数を指定し、その値をアプリケーションに注入することができます。これにより、異なる環境ごとに個別の設定を適用することができます。
また、複数の環境変数をファイルで一括設定することもできます。この方法では、複数の環境変数を手軽に管理でき、プロジェクトの規模が大きくなるほど利便性が高まります。

実際のコード例

サンプルコードの概要

環境変数を使うと、アプリケーションの設定を環境ごとに柔軟に切り替えることができます。Flutterでは、dart-defineを使用してコマンドラインから環境変数を設定し、その変数をアプリ内で使用することで、特定の環境に合わせた挙動を簡単に実現できます。環境変数は、APIのエンドポイントやアプリ機能の有効・無効の切り替えに特に役立ちます。

このサンプルコードは、API_URLENABLE_VALUEという2つの環境変数をFlutterアプリ内で使用し、動的にAPIの接続先を変えたり、特定の機能を有効化・無効化するものです。環境変数を用いたことで、開発・本番環境を簡単に切り替えられる点が特徴です。

const apiUrl = String.fromEnvironment('API_URL', defaultValue: 'http://localhost');
const enableValue = String.fromEnvironment('ENABLE_VALUE', defaultValue: 'false') == 'true';

class MyHomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Flutter環境変数の例'),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text('API URL: $apiUrl'),
            Text('機能有効: $enableValue'),
          ],
        ),
      ),
    );
  }
}

このコードでは、API_URLにデフォルト値としてhttp://localhostが設定されており、dart-defineを使用してコマンドラインから変更することができます。環境変数を設定しないと、そのままデフォルト値が使用されます。
また、ENABLE_VALUEは機能の有効・無効を切り替えるためのフラグとして利用されています。

主要部分の説明

Flutterで環境変数を使用する最大の利点は、異なる環境に応じて動作を簡単に切り替えられることです。例えば、開発環境ではローカルのサーバに接続し、本番環境では外部のAPIに接続する必要があるとき、API_URLを使うことで、コードを書き換えることなく接続先を変更できます。また、ENABLE_VALUEのように、機能を環境ごとに有効化・無効化することも簡単です。

例えば、以下のようにコマンドを使用して実行します。

flutter run --dart-define=API_URL=https://api.production.com --dart-define=ENABLE_VALUE=true

このコマンドを実行すると、アプリケーション内のAPI_URLENABLE_VALUEが指定された値に置き換えられ、https://api.production.comに接続し、機能が有効化された状態でアプリが動作します。

dart-defineの使用方法

コマンドラインでのdart-defineの設定

dart-defineは、Flutterのアプリケーション実行時に環境変数を設定するための機能です。これにより、異なる環境でアプリケーションの設定を動的に切り替えることができます。例えば、開発環境ではローカルサーバに接続し、本番環境では外部APIに接続するなどの用途に使えます。この設定は、コードを変更することなく、コマンドラインで簡単に行えます。

dart-defineを使う利点は、環境ごとの設定を容易に管理でき、アプリケーションの再ビルドなしで動作を変更できることです。これにより、開発スピードが向上し、環境ごとの設定ミスを防ぐことができます。特に、大規模なプロジェクトや頻繁に環境が変わる開発サイクルでは、この機能は非常に有用です。

以下のコマンド例を見てください。

flutter run --dart-define=API_URL=https://api.production.com --dart-define=ENABLE_VALUE=true

このコマンドは、API_URLENABLE_VALUEの値を実行時に設定し、Flutterアプリケーション内で使用できるようにします。これにより、環境ごとにAPIエンドポイントを簡単に切り替えたり、特定の機能を有効化したりできます。

dart-define-from-fileの利用

dart-define-from-fileは、環境変数を複数指定する場合に便利です。dart-defineと同様の設定を、JSONファイルなどで一括管理できるため、手動で長いコマンドを入力する必要がなくなります。これにより、設定の管理が効率化され、ミスの発生を減らすことができます。

この方法では、設定値を事前にファイルで定義し、実行時にそのファイルを読み込むだけで複数の環境変数を設定できます。特に、大規模なプロジェクトや多くの設定が必要な場合、手作業で入力するよりもはるかに管理しやすいです。

JSON形式

次のコマンドで、JSONファイルから環境変数を読み込みます。

flutter run --dart-define-from-file=dart_define_test.json

dart_define_test.jsonには、以下のような内容が記述されています。

{
  "API_URL":"http://flutter.salon/json/",
  "ENABLE_VALUE": "true"
}

このファイルを利用すれば、手作業で複数の環境変数をコマンドラインに入力する必要がなく、効率的に設定できます。

env形式(というのかな、、)

次のコマンドで、envファイルから環境変数を読み込みます。

flutter run --dart-define-from-file=dart_define_test.env

dart_define_test.envには、以下のような内容が記述されています。

API_URL=http://flutter.salon/env/
ENABLE_VALUE=true

JSON形式とenv形式の両方が使えるので、使いやすい方を使用してください。

環境変数をコード内で使用する方法

const修飾子を使用する理由

環境変数をFlutterコード内で使用する際には、const修飾子を使う必要があります。constを使う理由は、Flutterのビルドプロセスが定数として評価できる値を必要とするためです。環境変数をコード内で取得する際、String.fromEnvironmentメソッドを使って、コンパイル時に環境変数を定数として処理し、アプリケーションのパフォーマンスを最適化します。
const修飾子を使わずfinalを使用した場合、環境変数は取得されず、デフォルト値が表示され、アプリケーションが期待通りに動作しませんでした。

Q&A

Q1: Flutterで環境変数を使う理由は何ですか?

A1: Flutterで環境変数を使うことで、開発・本番環境など異なる環境ごとにAPIエンドポイントや設定を簡単に切り替えることができます。これにより、コードを変更する必要がなく、開発効率が向上し、設定ミスを防ぐことができます。

Q2: dart-defineを使うと何が便利ですか?

A2: dart-defineを使うことで、Flutterアプリの実行時にコマンドラインから環境変数を設定できます。これにより、設定を動的に変更でき、再ビルドすることなく異なる環境での設定が可能になります。

Q3: 環境変数をconstで取得する理由は何ですか?

A3: constで取得しないと正しく動作しません。また環境変数をconstで取得することで、コンパイル時に評価され、Flutterアプリのパフォーマンスを最適化できます。

まとめ

この記事を通して、Flutterでの環境変数の役割や利点、設定方法について理解しました。特に、dart-define--dart-define-from-fileを使ってコマンドラインやファイルから環境変数を設定する方法を学びました。

参考

ソース(main.dartにコピペして動作確認用)

import 'package:flutter/material.dart';

// flutter run
// flutter run --dart-define=API_URL=http://flutter.salon --dart-define=ENABLE_VALUE=true
// flutter run --dart-define-from-file=dart_define_test.json
// flutter run --dart-define-from-file=dart_define_test.env

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(),
      home: const MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({Key? key, required this.title}) : super(key: key);

  final String title;

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  @override
  Widget build(BuildContext context) {
    const apiUrl =
        String.fromEnvironment('API_URL', defaultValue: 'http://localhost');

    const enableValue =
        String.fromEnvironment('ENABLE_VALUE', defaultValue: 'false') == 'true';

    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Center(
        child: Column(
          children: [
            Text('apiUrl: $apiUrl'),
            Text('enableValue: $enableValue'),
          ],
        ),
      ),
    );
  }
}