逐次実行の例: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