😎

GetX取扱説明書

2021/09/24に公開約6,300字

目次

状態管理

getxの状態管理は大きく分けると下記2種類

  • リアクティブな状態管理ObxとGetX(状態管理名)
  • シンプルな状態管理なGetBuilder

Getx

controller.dart
class Controller extends GetxController {

  var counter = 0.obs;

  void increment() => counter.value++;

}

Obx同様に変数の値の最後に.obsをつけます。

view.dart
GetX<Controller>(
  init: Controller(),
  builder: (controller) => Text(
    '${controller.counter.value}',
  ),
),

getX<Controller>は基本的にボイラープレート(定型文)のないStreamBuilderです。
counterはRxInt型(.obsをつけているので)で、実際に使用するには.valueを追加する必要があります。

Obx

ビジネスロジックに下記を記述
var name = 'Jonatas Borges'.obs;
値の最後に.obsをつける
ビュー側でObx(() => )でwidgetを囲む
Obx(() => Text("${controller.name.value}"));

この2Stepだけでビジネスロジックが変更された瞬間にビュー側の値が変更されます。

ObxのController初期化

  • Get.put

既存インスタンスを使用

  • Get.find
Get.put
view.dart
class PageOne extends StatelessWidget {

  Controller controller = Get.put(Controller());
  // instead of Controller controller = Controller();

}

Controller controller = Get.put(Controller());ここでControllerのインスタンス生成をしてスコープ内でcontroller(Controllerのインスタンス)が使用できるようになります。
このクラスのすべての子ルートでコントローラを利用できるようになります。アプリ内のどこからでも、同じインスタンスを簡単に取得できるようになります。

Get.find
view.dart
class PageSeven extends StatelessWidget {

  Controller controller = Get.find();

}

Get.findで同じインスタンスを別のクラスで使用することができます。

GetBuilder

controller.dart
class Controller extends GetxController {

  int counter = 0;

  void increment() {
    counter++;
    update(); // look here!
  }

}

GetBuilderにはupdate()がありこれによりビュー側に変更を知らせることができます。
ビューを見てみましょう

view.dart
GetBuilder<Controller>( // specify type as Controller
  init: Controller(), // intialize with the Controller
  builder: (value) => Text(
    '${value.counter}', // value is an instance of Controller.
  ),
),

GetBuilder<Controller>( // no need to initialize Controller ever again, just mention the type
  builder: (value) => Text(
    '${value.counter}', // counter is updated when increment() is called
  ),
),

ビューの一つ目のGetBuilderでinitしているので二つ目のGetBuilderでは初期化をする必要がないです。
Controller を初期化する必要があるのは、GetBuilder で初めて使用するときだけです。他のすべての GetBuilder は、アプリ内のどこにあっても、最初の GetBuilder の状態を自動的に共有します。
GetBuilder は基本的に StatefulWidget の代わりとなります。すべてのページをステートレスにしておき、特定のウィジェットを GetBuilder でラップすることができます。これは、コードを整理しながら、一時的な状態を管理する良い方法です。
また、一意のIDを割り当てることで、どのウィジェットを更新するかを細かく管理することができます。

view.dart
GetBuilder<Controller>(
  id: 'aVeryUniqueID', // here
  init: Controller(),
  builder: (value) => Text(
    '${value.counter}', // this will update
  ),
),

GetBuilder<Controller>(
  id: 'someOtherID', // here
  init: Controller(),
  builder: (value) => Text(
    '${value.counter}', // this won't update
  ),
),
controller.dart
class Controller extends GetxController {

  int counter = 0;

  void increment() {
    counter++;
    update(['aVeryUniqueID']); // and then here
  }

}

状態管理の選択

GetBuilder

  • 状態はビルダー間で共有されるので、多くのRAMを消費したくない場合
  • streamを使いたくない場合

GetX

  • リアクティブプログラミングの威力を発揮したい場合
  • 不要なwidgetの再描画を減らしたい場合(変数の値が "Garg "から "Garg "に変更された場合、ウィジェットは再描画されません。)
  • コントローラのインスタンス化をしたくない場合

Obx

  • シンプルな構文を好む場合。
  • 同じウィジェット内で複数のコントローラを使用する場合。(Obxは型を必要としないので、いくつものコントローラで使用することができる)

画面遷移

NextScreenに画面遷移

sample.dart
Get.to(NextScreen());

一つ前の画面に戻る

sample.dart
Get.back();

前の画面に戻れない画面遷移

sample.dart
Get.off(NextScreen());

これまでの経路をすべてキャンセルする画面遷移

sample.dart
Get.offAll(NextScreen());

使用例は投票やショッピングカートなど

routeでの画面遷移

routeでの画面遷移は省略します
もしroute指定の画面遷移が知りたい方がいらっしゃいましたらこちら

https://github.com/jonataslaw/getx/blob/master/documentation/en_US/route_management.md#navigation-with-named-routes

Utils

SnackBar

sample.dart
Get.snackbar("タイトル", "詳細の内容");

ダイアログ表示

sample.dart
Get.defaultDialog(
  title: "タイトル",
  middleText: "詳細の内容",
  textCancel: "キャンセルボタン",
);

ボトムシート

sample.dart
Get.bottomSheet(
  Container(
    height: 300,
    color: Colors.white,
    child: Text("内容"),
));

GetX使用例と復習

Step1

  • GetXパッケージをinstallをする
  • MaterialAppをGetMaterialAppに変える
main.dart
void main() => runApp(GetMaterialApp(home: Home()));

Step2

ビジネスロジッククラスを作成し、その中にすべての変数、メソッド、およびコントローラーを配置します。単純な「.obs」を使用して、任意の変数を監視可能にすることができます。

controller.dart
class Controller extends GetxController{
  var count = 0.obs;
  increment() => count++;
}

※GetxControllerをextendsする

Step3

ビューを作成し、StatelessWidgetを使用して、RAMを節約します。Getを使用すると、StatefulWidgetを使用する必要がなくなる場合があります。

view.dart
class Home extends StatelessWidget {

  
  Widget build(context) {

    // Instantiate your class using Get.put() to make it available for all "child" routes there.
    final Controller c = Get.put(Controller());

    return Scaffold(
      // Use Obx(()=> to update Text() whenever count is changed.
      appBar: AppBar(title: Obx(() => Text("Clicks: ${c.count.value}"))),

      // Replace the 8 lines Navigator.push by a simple Get.to(). You don't need context
      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 {
  // You can ask Get to find a Controller that is being used by another page and redirect you to it.
  final Controller c = Get.find();

  
  Widget build(context){
     // Access the updated count variable
     return Scaffold(body: Center(child: Text("${c.count.value}")));
  }
}

final Controller c = Get.put(Controller());について
Get.put(クラス名())でクラス名で指定したクラスをインスタンス化して記述したスコープでそのクラスが利用可能になる。

appBar: AppBar(title: Obx(() => Text("Clicks: ${c.count.value}"))),について
var count = 0.obs;のcountが変更されるとview側のobx(() => )で囲んだTextが変更される

final Controller c = Get.find();について
Get.find();は他のページで使われているコントローラーを見つけて、それを使用できます。
公式では以下のように書いています。

[補足]ここで上記のコードでGet.findで取得したデータを表示するTextがObxで囲んでいないのかというと単純に状態をwidgetに伝えようしていないから(Textのwidgetをリアクティブに更新しようとしてしない)です。

参考URL

https://github.com/jonataslaw/getx/blob/master/documentation/en_US/route_management.md#navigation-with-named-routes

https://pub.dev/packages/get

https://medium.com/flutter-community/the-flutter-getx-ecosystem-state-management-881c7235511d

Discussion

ログインするとコメントできます