Open6
Flutter GetXについて調べてみる
興味をもった経緯
普段はProviderを使用しているが、Riverpodが流行ってきているのをみて、状態管理に興味を持った。
GetXというのがgithubのスター数でProvider並みの数を獲得している。そのうえ日本語での記事がほとんどないので調べてみようと思った。
英語のpubdevが充実していそう。だが英語は得意ではないので、実際に触ってみてメモすることにした。
ちゃんと公式サイトにも列挙されているアプローチ
まずはデモのカウンターアプリを動かしてみる。
main.dart
import 'package:flutter/material.dart';
import 'package:get/get.dart';
//MaterialAppをGetMaterialAppに置き換える
void main() => runApp(GetMaterialApp(home: Home()));
class Controller extends GetxController {
//obsをつけると変更を監視できるようになる。
var count = 0.obs;
increment() => count++;
}
class Home extends StatelessWidget {
Widget build(context) {
// Get.put()を使ってクラスをインスタンス化し、配下のウィジェットで利用できるようにする。
final Controller c = Get.put(Controller());
return Scaffold(
// カウントが変更されるたびにText()を更新するためにObx(()=>を使用します。
appBar: AppBar(title: Obx(() => Text("Clicks: ${c.count}"))),
// Get.to()で画面遷移ができる。Navigatorに比べたらめちゃくちゃ簡単
body: Center(
child: ElevatedButton(
child: Text("Go to Other"), onPressed: () => Get.to(Other()))),
floatingActionButton: FloatingActionButton(
child: Icon(Icons.add), onPressed: c.increment));
}
}
class Other extends StatelessWidget {
// 他のページで使われているコントローラーを見つけて、それを使用できる。
final Controller c = Get.find();
Widget build(context) {
// 更新された変数にアクセス
return Scaffold(body: Center(child: Text("${c.count}")));
}
}
こんな感じで
FloatingActionButtonを押すとタイトル部分のカウントが増える
ボタンを押してページ遷移してもGet.findで値を参照できている。
GetXには大きく3つの役割がある。
- 状態管理
- ルート管理
- 依存性管理
ルート管理
getxはcontextなしで、ルーティングを使用することができる。
使い方
MateriulAppの代わりにGetMaterialAppを使用する。
GetMaterialApp(
home: MyHome(),
)
画面遷移
Get.to(NextScreen()); //次のページへ
Get.back(); //前のページへ
Get.off(NextScreen()); //前の画面に戻れないやつ
Get.offAll(NextScreen()); //以前の画面を全部キャンセルするやつ
データの受け渡しもできる
var data = await Get.to(Payment()); //遷移後戻ってきたらdataの中に値が入る
Get.back(result: 'success'); //遷移先から戻る際にデータを受け渡せる
if(data == 'success') madeAnything(); //こんな感じで使える
名前付き
Get.toNamed('/second');
Get.offNamed("/second");
Get.offAllNamed("/second");
Get.toNamed("/second", arguments: 'データ渡せる');
名前付きルートの定義の方法
void main() {
runApp(
GetMaterialApp(
initialRoute: '/',
getPages: [
GetPage(name: '/', page: () => MyHomePage()),
GetPage(name: '/second', page: () => Second()),
GetPage(
name: '/third',
page: () => Third(),
transition: Transition.zoom
),
],
)
);
}
動的なルーティングにも対応
void main() {
runApp(
GetMaterialApp(
initialRoute: '/',
getPages: [
GetPage(
name: '/profile/:user',
page: () => UserProfile(),
),
],
)
);
}
//これで遷移すると
Get.toNamed("/profile/34954");
//次の画面で値を拾える
print(Get.parameters['user']); // 34954
//こういう書き方でもいける
Get.toNamed("/profile/34954?flag=true&country=japan");
print(Get.parameters['country']); //japan
他にもcontextに依存せずに使える便利な機能があるので簡単に紹介
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
ElevatedButton(
child: Text("スナックバーを表示します"),
onPressed: () {
Get.snackbar(
"スナックバーだよ",
"コンテキスト必要ないよ",
);
},
),
ElevatedButton(
child: Text("ダイアログを表示します"),
onPressed: () {
Get.defaultDialog(
title: "ダイアログだよ",
middleText: "コンテキスト必要ないよ",
textCancel: "キャンセル",
);
},
),
ElevatedButton(
child: Text("ボトムシートを表示します"),
onPressed: () {
Get.bottomSheet(Container(
height: 500,
color: Colors.white,
child: Center(
child: Text("ボトムシートだよ、コンテキスト必要ないよ"),
),
));
},
),
],
),
),
画面はこんな感じで試してみました。
スナックバー
ダイアログ表示
ボトムシート
シンプルに書いたので見た目はイマイチですが、
カスタマイズはできるようです。
今回はViewのみでデモを書いていますが、contextを書かなくていいため、
ロジック側にダイアログの表示などを書きやすくなるメリットがあります。