[Flutter]状態管理:GetX の使い方

GetXとは、Flutterアプリケーションをより簡単かつ迅速に開発するためのオープンソースパッケージで、状態管理、ルーティング、依存性注入などの機能を提供しています。GetXを使用することで、アプリケーションの開発速度を向上させ、よりシンプルなコードを書くことができます。

以下は、GetXパッケージを使用する際に知っておくべき重要な機能についての詳細です。

目次

インストール

FlutterのGetXパッケージをインストールする手順は次のとおりです:

  1. pubspec.yamlファイルを開きます。これはFlutterプロジェクトのルートディレクトリにあります。
  2. dependenciesセクションに移動し、getパッケージを追加します。以下のように記述します:
dependencies:
  flutter:
    sdk: flutter
  get: ^4.6.5

ここでは、バージョン4.6.5のGetXパッケージを使用するように指定していますが、最新のバージョンを使用することもできます。バージョン指定のセマンティックバージョニング(Semantic Versioning)に基づいた制約を追加することもできます。

  1. pubspec.yamlファイルを保存します。
  2. ターミナルまたはコマンドプロンプトを開き、プロジェクトのルートディレクトリに移動します。
  3. 以下のコマンドを実行して、GetXパッケージをインストールします:(エディタがVScodeでは自動実行されるため省略可)
flutter pub get

これにより、指定したバージョンのGetXパッケージがプロジェクトに追加されます。

GetXパッケージが正常にインストールされると、FlutterプロジェクトでGetXの機能を使用する準備が整います。必要に応じて、import 'package:get/get.dart';のようにしてGetXパッケージをインポートして使用することができます。

状態管理

GetXには、状態管理のためのState Managementパッケージが含まれています。GetXのState Managementは、Flutterの標準的なState Management方法であるsetStateやStreamBuilderなどの煩わしい部分を自動的に処理し、状態を簡単かつ効率的に管理できるようにしてくれます。

以下は、GetXを使用した状態管理の例です。

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

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'My App',
      home: MyHomePage(),
    );
  }
}

class MyController extends GetxController {
  var count = 0.obs; // countが監視され、変更されるたびに再レンダリングが行われます。

  void increment() {
    count++;
  }
}

class MyHomePage extends StatelessWidget {
  final MyController controller = Get.put(MyController());

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('GetX Example'),
      ),
      body: Center(
        child: Obx(() => Text(
              '${controller.count.value}',
              style: TextStyle(fontSize: 24),
            )),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: controller.increment,
        tooltip: 'Increment',
        child: Icon(Icons.add),
      ),
    );
  }
}

上記の例では、MyControllerクラスで状態を管理し、MyHomePageクラスでそれを使用しています。MyControllerクラスでは、count変数をObservable(obs)にし、その値が変更されるたびに自動的に再レンダリングが行われます。MyHomePageクラスでは、Obxウィジェットを使用して、count変数を表示します。また、floatingActionButtonには、MyControllerクラスで定義されたincrement関数をバインドしています。

ルーティング

GetXは、アプリケーション内の画面遷移を管理するためのルーティングパッケージも提供しています。このパッケージを使用すると、ネストされたルーティング、名前付きルート、パラメータの受け渡しなどが簡単に実現できます。

以下は、GetXを使用したルーティングの例です。

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

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return GetMaterialApp(
      title: 'GetX Routing Example',
      initialRoute: '/',
      getPages: [
        GetPage(name: '/', page: () => MyHomePage()),
        GetPage(name: '/second', page: () => SecondPage()),
        GetPage(name: '/third/', page: () => ThirdPage()),
      ],
    );
  }
}

class MyHomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('GetX Routing Example'),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            ElevatedButton(
              child: Text('Go to second page'),
              onPressed: () => Get.toNamed('/second'),
            ),
            ElevatedButton(
                child: Text('Go to third page'),
                onPressed: () {
                  String data = 'This is some data!';
                  Get.toNamed('/third', arguments: data);
                }),
          ],
        ),
      ),
    );
  }
}

class SecondPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Second Page'),
      ),
      body: Center(
        child: ElevatedButton(
          child: Text('Go back'),
          onPressed: () => Get.back(),
        ),
      ),
    );
  }
}

class ThirdPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    final String data = Get.arguments;

    return Scaffold(
      appBar: AppBar(
        title: Text('Third Page'),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Text(data),
            ElevatedButton(
              child: Text('Go back'),
              onPressed: () => Get.back(),
            ),
          ],
        ),
      ),
    );
  }
}

上記の例では、GetMaterialAppを使用して、アプリケーション全体でGetXルーティングを有効にします。getPagesプロパティには、名前付きルートと各ページに対応するウィジェットを定義します。MyHomePageクラスでは、Get.toNamedを使用して、’/second’と’/third/Hello World!’という名前付きルートに遷移するボタンを表示します。SecondPageクラスとThirdPageクラスでは、Get.backを使用して、前のページに戻るボタンを表示します。また、ThirdPageクラスでは、Get.parametersを使用して、’/third/:data’のパラメータを取得します。

依存性注入

GetXには、依存性注入のためのパッケージも含まれています。依存性注入を使用することで、アプリケーション全体でインスタンスを共有することができ、再利用性とテスト性を向上させることができます。

以下は、GetXを使用した依存性注入の例です。

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

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return GetMaterialApp(
      title: 'Dependency Injection',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(),
    );
  }
}

class MyHomePage extends StatelessWidget {
  final MyController myController = Get.put(MyController());

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Dependency Injection'),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Obx(() => Text('Counter: ${myController.counter.value}')),
            ElevatedButton(
              child: Text('Increment'),
              onPressed: () {
                myController.increment();
              },
            ),
          ],
        ),
      ),
    );
  }
}

class MyController extends GetxController {
  var counter = 0.obs;

  void increment() {
    counter.value++;
  }
}

このサンプルコードでは、Getxの依存性注入を使用してMyControllerクラスを注入しています。MyControllerは状態管理用のコントローラーです。counterというRx変数を持ち、increment()メソッドでカウンターを増やすことができます。

MyHomePageウィジェットでは、MyControllerのインスタンスを取得し、Obxウィジェットを使用してcounterの値を監視しています。カウンターの値と増加ボタンが表示され、ボタンを押すとカウンターが増加します。

このコードを実行すると、Getxの依存性注入を使用して状態管理を行う基本的なカウンターアプリが表示されます。

ダイアログ(Dialog)

ダイアログは、ユーザーに対して情報を提示したり、確認を取ったりするために使用されます。 GetXを使用すると、簡単にカスタマイズできるダイアログを表示することができます。

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

// 依存性のバインド用のクラス
class UserRepository {
  void login(String username, String password) {
    // ログイン処理の実装
    print('ログイン成功: $username');
  }
}

// 依存性の解決用のコントローラークラス
class LoginController extends GetxController {
  final UserRepository userRepository;

  LoginController(this.userRepository);

  void login(String username, String password) {
    userRepository.login(username, password);
  }

  void showDialog() {
    Get.dialog(
      AlertDialog(
        title: Text('ダイアログ'),
        content: Text('ダイアログのコンテンツ'),
        actions: [
          TextButton(
            onPressed: () {
              Get.back();
            },
            child: Text('閉じる'),
          ),
        ],
      ),
    );
  }
}

// ログイン画面
class LoginPage extends StatelessWidget {
  final LoginController loginController = Get.find();

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('ログイン'),
      ),
      body: Center(
        child: ElevatedButton(
          child: Text('ログイン'),
          onPressed: () {
            loginController.login('username', 'password');
            loginController.showDialog();
          },
        ),
      ),
    );
  }
}

void main() {
  // 依存性のバインド
  Get.put(UserRepository());
  Get.put(LoginController(Get.find<UserRepository>()));

  // アプリケーションの起動
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return GetMaterialApp(
      home: LoginPage(),
    );
  }
}

上記のコードでは、LoginController クラスに showDialog() メソッドを追加しています。このメソッドは、Get.dialog() メソッドを使用してダイアログを表示します。

LoginPage ウィジェットのボタンのクリックイベントで、まず loginController.login() メソッドが呼ばれてログイン処理が実行され、その後 loginController.showDialog() メソッドが呼ばれてダイアログが表示されます。

ダイアログは AlertDialog を使用して作成されており、タイトルやコンテンツ、閉じるボタンが含まれています。閉じるボタンの押下時には Get.back() メソッドが呼ばれてダイアログが閉じられます。

このようにして、ログインボタンのクリック時にログイン処理が行われ、その後ダイアログが表示される仕組みが実装されています。

スナックバー(Snackbar)

スナックバーは、ユーザーに対してフィードバックを提供するために使用されます。 GetXを使用すると、簡単にスナックバーを表示することができます。

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

// 依存性のバインド用のクラス
class UserRepository {
  void login(String username, String password) {
    // ログイン処理の実装
    print('ログイン成功: $username');
  }
}

// 依存性の解決用のコントローラークラス
class LoginController extends GetxController {
  final UserRepository userRepository;

  LoginController(this.userRepository);

  void login(String username, String password) {
    userRepository.login(username, password);
  }

  void showSnackbar() {
    Get.snackbar(
      'スナックバー',
      'スナックバーメッセージ',
      backgroundColor: Colors.grey[900],
      colorText: Colors.white,
      snackPosition: SnackPosition.BOTTOM,
      duration: Duration(seconds: 3),
    );
  }
}

// ログイン画面
class LoginPage extends StatelessWidget {
  final LoginController loginController = Get.find();

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('ログイン'),
      ),
      body: Center(
        child: ElevatedButton(
          child: Text('ログイン'),
          onPressed: () {
            loginController.login('username', 'password');
            loginController.showSnackbar();
          },
        ),
      ),
    );
  }
}

void main() {
  // 依存性のバインド
  Get.put(UserRepository());
  Get.put(LoginController(Get.find<UserRepository>()));

  // アプリケーションの起動
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return GetMaterialApp(
      home: LoginPage(),
    );
  }
}

上記のコードでは、LoginController クラスに showSnackbar() メソッドを追加しています。このメソッドは、Get.snackbar() メソッドを使用してスナックバーを表示します。

LoginPage ウィジェットのボタンのクリックイベントで、まず loginController.login() メソッドが呼ばれてログイン処理が実行され、その後 loginController.showSnackbar() メソッドが呼ばれてスナックバーが表示されます。

スナックバーは Get.snackbar() を使用して作成されており、タイトルやメッセージ、背景色、テキスト色、表示位置、表示時間などの設定が行われています。

ロギング

ログは、アプリケーションの状態を確認するために使用されます。 GetXを使用すると、簡単にログを出力することができます。

Get.log('Log Message');

このコードでは、 Get.log()メソッドを使用して、ログを出力しています。ログメッセージは、コンソールに出力されます。

HTTPクライアント(HTTP Client)

HTTPクライアントは、APIからデータを取得するために使用されます。 GetXを使用すると、簡単にHTTPクライアントを作成することができます。

import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:http/http.dart' as http;

// ポストモデル
class Post {
  final int id;
  final String title;
  final String body;

  Post({required this.id, required this.title, required this.body});

  factory Post.fromJson(Map<String, dynamic> json) {
    return Post(
      id: json['id'],
      title: json['title'],
      body: json['body'],
    );
  }
}

// 依存性のバインド用のクラス
class PostRepository {
  final String apiUrl = 'https://jsonplaceholder.typicode.com/posts';

  Future<List<Post>> fetchPosts() async {
    final response = await http.get(Uri.parse(apiUrl));

    if (response.statusCode == 200) {
      List<dynamic> jsonResponse = json.decode(response.body);
      return jsonResponse.map((data) => Post.fromJson(data)).toList();
    } else {
      throw Exception('Failed to fetch posts');
    }
  }
}

// 依存性の解決用のコントローラークラス
class HomeController extends GetxController {
  final PostRepository postRepository;

  HomeController(this.postRepository);

  final posts = <Post>[].obs;

  @override
  void onInit() {
    fetchPosts();
    super.onInit();
  }

  void fetchPosts() async {
    try {
      List<Post> fetchedPosts = await postRepository.fetchPosts();
      posts.assignAll(fetchedPosts);
    } catch (e) {
      print(e);
    }
  }
}

// ホーム画面
class HomePage extends StatelessWidget {
  final HomeController homeController =
      Get.put(HomeController(PostRepository()));

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Posts'),
      ),
      body: Obx(
        () => ListView.builder(
          itemCount: homeController.posts.length,
          itemBuilder: (context, index) {
            return ListTile(
              title: Text(homeController.posts[index].title),
              subtitle: Text(homeController.posts[index].body),
            );
          },
        ),
      ),
    );
  }
}

void main() {
  // アプリケーションの起動
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return GetMaterialApp(
      home: HomePage(),
    );
  }
}

上記のコードでは、Post クラスを作成しています。これは、取得した投稿データのモデルを表しています。

PostRepository クラスでは、外部APIから投稿データを取得するためのメソッド fetchPosts() を実装しています。このメソッドは、http パッケージを使用して外部APIにGETリクエストを送信し、レスポンスを受け取ります。レスポンスのステータスコードが200の場合はデータをパースし、Post オブジェクトのリストとして返します。

HomePage ウィジェットでは、HomeController のインスタンスを生成し、Get.put() を使用して依存性の注入を行っています。

HomePage ウィジェットのビルドメソッド内で、homeController.posts を監視しているため、データが更新されると自動的にUIが更新されます。ListView.builder を使用して、取得した投稿データをリスト形式で表示しています。

main() 関数では、MyApp を起動しています。MyApp クラスは、GetMaterialApp を使用してルートウィジェットをラップしています。

このコードを実行すると、外部APIから投稿データを取得し、ホーム画面に表示することができます。

バリデーション(Validation)

バリデーションは、フォームや入力欄に入力されたデータが正しい形式であるかを確認するために使用されます。 GetXは、簡単なバリデーションを提供するために作成されています。

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

// バリデーション用のクラス
class ValidationController extends GetxController {
  final TextEditingController textEditingController = TextEditingController();
  final RxBool isEmailValid = false.obs;

  void validateEmail(String email) {
    // 簡単なバリデーションの例:入力がメールアドレス形式かどうかを判定
    final emailRegex = RegExp(r'^[\w-]+(\.[\w-]+)*@[\w-]+(\.[\w-]+)+$');
    isEmailValid.value = emailRegex.hasMatch(email);
  }
}

// バリデーション画面
class ValidationPage extends StatelessWidget {
  final ValidationController validationController =
      Get.put(ValidationController());

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('バリデーション'),
      ),
      body: Padding(
        padding: EdgeInsets.all(16.0),
        child: Column(
          children: [
            Obx(() => TextField(
                  controller: validationController.textEditingController,
                  onChanged: (value) {
                    validationController.validateEmail(value);
                  },
                  decoration: InputDecoration(
                    labelText: 'メールアドレス',
                    errorText: validationController.isEmailValid.value
                        ? null
                        : '有効なメールアドレスを入力してください',
                  ),
                )),
            ElevatedButton(
              child: Text('送信'),
              onPressed: () {
                if (validationController.isEmailValid.value) {
                  // バリデーションが成功した場合の処理
                  print(
                      'メールアドレス: ${validationController.textEditingController.text}');
                } else {
                  // バリデーションが失敗した場合の処理
                  print('バリデーションエラー');
                }
              },
            ),
          ],
        ),
      ),
    );
  }
}

void main() {
  // アプリケーションの起動
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return GetMaterialApp(
      home: ValidationPage(),
    );
  }
}

上記のコードでは、ValidationController クラスを作成しています。このクラスは、バリデーションのためのコントローラーです。

ValidationController クラスには、TextEditingControllerisEmailValid という RxBool オブジェクトがあります。textEditingController は、入力フィールドのテキストを制御するために使用されます。isEmailValid は、メールアドレスのバリデーション結果を格納するためのオブジェクトです。

ValidationPage ウィジェットでは、ValidationController のインスタンスを生成し、Get.put() を使用して依存性の注入を行っています。

ValidationPage ウィジェットのビルドメソッド内では、TextField を使用してメールアドレスの入力フィールドを作成しています。入力値が変更されるたびに、validationController.validateEmail() メソッドが呼ばれてバリデーションが行われ、errorText を通じてエラーメッセージが表示されます。

ValidationPage ウィジェットのビルドメソッド内に、「送信」ボタンが追加しています。「送信」ボタンが押された際に、validationController.isEmailValid.value をチェックしてバリデーションが成功しているかどうかを確認しています。バリデーションが成功している場合は、入力されたメールアドレスを表示する処理が行われます。バリデーションが失敗している場合は、バリデーションエラーを表示する処理が行われます。

テーマ(Themes)

テーマは、アプリケーションの見た目やスタイルを設定するために使用されます。 GetXは、簡単なテーマ設定を提供するために作成されています。

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

// メイン関数
void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'テーマの例',
      theme: ThemeData(
        // テーマの設定
        primaryColor: Colors.blue, // アクセントカラー
        fontFamily: 'Roboto', // フォントファミリー
        textTheme: TextTheme(
          headlineSmall: TextStyle(
              fontSize: 24.0, fontWeight: FontWeight.bold), // タイトルのスタイル
          bodySmall: TextStyle(fontSize: 16.0), // 本文のスタイル
        ),
        colorScheme:
            ColorScheme.fromSwatch().copyWith(secondary: Colors.orange),
      ),
      home: HomePage(),
    );
  }
}

class HomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('テーマの例'),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Text(
              'プライマリーカラー',
              style: Theme.of(context).textTheme.headlineMedium,
            ),
            SizedBox(height: 20.0),
            Container(
              width: 200,
              height: 50,
              color: Theme.of(context).primaryColor,
            ),
            SizedBox(height: 40.0),
            Text(
              'アクセントカラー',
              style: Theme.of(context).textTheme.headlineLarge,
            ),
            SizedBox(height: 20.0),
            Container(
              width: 200,
              height: 50,
              color: Theme.of(context).colorScheme.secondary,
            ),
            SizedBox(height: 40.0),
            Text(
              'フォントファミリー',
              style: Theme.of(context).textTheme.headlineMedium,
            ),
            SizedBox(height: 20.0),
            Text(
              'Roboto',
              style: Theme.of(context).textTheme.bodyMedium,
            ),
          ],
        ),
      ),
    );
  }
}

上記のコードでは、MyApp クラス内でテーマを設定しています。theme プロパティを使用して、プライマリーカラーやアクセントカラー、フォントファミリーなどを指定しています。

HomePage クラスでは、指定したテーマを利用してウィジェットを作成しています。例えば、Theme.of(context).textTheme.headlineMedium を使用することで、テーマで指定したタイトルのスタイルを取得して適用しています。

Text ウィジェットや Container ウィジェットなどを使って、プライマリーカラーやアクセントカラー、フォントファミリーが正しく適用されているかどうかを表示しています。

まとめ

以上が、GetXの機能の一部についての説明でした。GetXは、Flutterの開発をより簡単にするために作成されたライブラリであり、簡単なコードで高機能なアプリケーションを作成することができます。GetXの機能を活用することで、アプリケーションの開発をより迅速かつ簡単に行うことができます。

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!
目次