GetXによる逐次実行実装例

投稿者: | 2025年6月5日

逐次実行の例:UIがあるパターン

Reactive Peogrammingで逐次実行のパターンを6つみてきたわけだが、ここで一つGetXを用いたUIを伴うサンプルを提示する。

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

void main() {
  runApp(GetMaterialApp(
    home: StartupPage(),
  ));
}

class ProgressController extends GetxController {
  var progress = 0.0.obs;
  var step = 0.obs; // 0:未開始, 1:A, 2:B, 3:C, 4:完了
}

class StartupPage extends StatelessWidget {
  final ProgressController controller = Get.put(ProgressController());

  @override
  Widget build(BuildContext context) {
    _startSequence();

    return Scaffold(
      appBar: AppBar(title: Text('初期化中')),
      body: Center(
        child: Obx(() {
          String label;
          switch (controller.step.value) {
            case 1:
              label = 'ステップ A 実行中...';
              break;
            case 2:
              label = 'ステップ B 実行中...';
              break;
            case 3:
              label = 'ステップ C 実行中...';
              break;
            case 4:
              label = '完了!';
              break;
            default:
              label = '準備中...';
          }
          return Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
              Text('$label ${(controller.progress.value * 100).toStringAsFixed(0)}%'),
              SizedBox(height: 20),
              LinearProgressIndicator(value: controller.progress.value),
            ],
          );
        }),
      ),
    );
  }

  void _startSequence() async {
    final tasks = [_heavyTaskA, _heavyTaskB, _heavyTaskC];
    for (int i = 0; i < tasks.length; i++) {
      controller.step.value = i + 1;
      await _runInIsolate(tasks[i]);
    }
    controller.step.value = 4; // 完了
  }

  Future<void> _runInIsolate(Function(SendPort) task) async {
    final receivePort = ReceivePort();
    final isolate = await Isolate.spawn(task, receivePort.sendPort);

    final completer = Completer<void>();
    receivePort.listen((message) {
      if (message is double) {
        controller.progress.value = message;
      } else if (message == 'done') {
        receivePort.close();
        isolate.kill(priority: Isolate.immediate);
        completer.complete();
      }
    });

    return completer.future;
  }
}

// 各ステップの重い処理(ダミー)
void _heavyTaskA(SendPort sendPort) async {
  for (int i = 0; i <= 10; i++) {
    await Future.delayed(Duration(milliseconds: 200));
    sendPort.send(i / 10.0);
  }
  sendPort.send('done');
}

void _heavyTaskB(SendPort sendPort) async {
  for (int i = 0; i <= 10; i++) {
    await Future.delayed(Duration(milliseconds: 300));
    sendPort.send(i / 10.0);
  }
  sendPort.send('done');
}

void _heavyTaskC(SendPort sendPort) async {
  for (int i = 0; i <= 10; i++) {
    await Future.delayed(Duration(milliseconds: 150));
    sendPort.send(i / 10.0);
  }
  sendPort.send('done');
}

pubspec.ymlの更新も必要。

dependencies:
  flutter:
    sdk: flutter
  get: ^4.6.6

コメントを残す