【アプリ開発】FlutterとRiverpodを用いた、外部サイト遷移処理中のローディング状態処理とボタン非活性化
はじめに
Flutterアプリから外部サイトへ遷移させたい場合で、遷移まで時間がかかる(APIリクエストしてresponseの情報を元に遷移するなど)際の処理として
ローディングアイコンを表示して、遷移まではボタンを非活性化する
遷移するまでの間にユーザーが画面を移動しないようにする
などの制御ニーズが発生する。
Flutter と Riverpod を利用してローディングの状態管理を行い、ボタンの非活性化と、ナビゲーションの戻るボタンの無効化を行ったので、備忘録記載。
コード全体像
import 'package:flutter/material.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:url_launcher/url_launcher.dart';
final loadingProvider = StateProvider<bool>((ref) => false);
class DataRetrievalPage extends HookConsumerWidget {
const DataRetrievalPage({super.key});
@override
Widget build(BuildContext context, WidgetRef ref) {
final isLoading = ref.watch(loadingProvider);
return WillPopScope(
onWillPop: () async => !isLoading,
child: Scaffold(
appBar: AppBar(
title: const Text('テスト画面'),
leading: isLoading
? null
: IconButton(
icon: const Icon(Icons.arrow_back),
onPressed: () => Navigator.of(context).pop(),
),
),
body: const Padding(
padding: EdgeInsets.all(16.0),
child: _Body(),
),
),
);
}
}
class _Body extends ConsumerWidget {
const _Body();
@override
Widget build(BuildContext context, WidgetRef ref) {
final isLoading = ref.watch(loadingProvider);
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Text(
'外部サイトに遷移します',
style: TextStyle(
fontSize: 16,
height: 1.5,
),
),
const SizedBox(height: 24),
Center(
child: Stack(
alignment: Alignment.center,
children: [
ElevatedButton(
onPressed: isLoading ? null : () async {
ref.read(loadingProvider.notifier).state = true;
try {
final urlString = await fetchExternalUrl();
final url = Uri.parse(urlString);
if (await canLaunchUrl(url)) {
await launchUrl(url);
} else {
throw Exception('Could not launch $url');
}
} catch (e) {
ref.watch(exceptionHelperProvider).showMessage(e);
} finally {
ref.read(loadingProvider.notifier).state = false;
}
},
child: const Text('外部サイトに遷移'),
),
if (isLoading)
const Positioned(
child: CircularProgressIndicator(),
),
],
),
),
],
);
}
}
ローディング状態の管理
loadingProvider という StateProvider を使用してローディングの状態を管理。
続きは、こちらで記載しています。
いいなと思ったら応援しよう!
よろしければサポートお願いします!いただいたサポートはクリエイターとしての活動費に使わせていただきます!