Skip to content

Instantly share code, notes, and snippets.

@take4blue
Created July 29, 2022 10:06
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save take4blue/06c438db86097a5490e56dd039249d80 to your computer and use it in GitHub Desktop.
Save take4blue/06c438db86097a5490e56dd039249d80 to your computer and use it in GitHub Desktop.
FutureBuilderを拡張してwaitingになるまでの時間を設定できるようにした。
import 'dart:async';
import 'package:flutter/material.dart';
/// FutureBuilderを拡張してwaitingになるまでの時間を設定できるようにした。
/// FutureBuilderからの変更点はactiveTimeを設定できる点。
/// activeTimeが経過する前は[ConnectionState.active]で経過してデータが
/// そろっていない場合は[ConnectionState.waiting]になる。
class FutureBuilderExt<T> extends FutureBuilder<T> {
const FutureBuilderExt({
Key? key,
Future<T>? future,
final T? initialData,
required AsyncWidgetBuilder<T> builder,
this.activeTime,
}) : super(
future: future,
initialData: initialData,
builder: builder,
key: key);
/// Future呼び出し後、activeとしている時間。
final Duration? activeTime;
@override
State<FutureBuilderExt<T>> createState() => _FutureBuilderExtState<T>();
}
/// [_FutureBuilderState<T>]をコピーして、[_subscribe]内の処理を変更。
/// [activeTime]がnull以外の場合、初期ステータスを[ConnectionState.active]
/// にして[activeTime]経過後[ConnectionState.waiting]に変更するようにしている。
class _FutureBuilderExtState<T> extends State<FutureBuilderExt<T>> {
Object? _activeCallbackIdentity;
late AsyncSnapshot<T> _snapshot;
@override
void initState() {
super.initState();
_snapshot = widget.initialData == null
? AsyncSnapshot<T>.nothing()
: AsyncSnapshot<T>.withData(
ConnectionState.none, widget.initialData as T);
_subscribe();
}
@override
void didUpdateWidget(FutureBuilderExt<T> oldWidget) {
super.didUpdateWidget(oldWidget);
if (oldWidget.future != widget.future) {
if (_activeCallbackIdentity != null) {
_unsubscribe();
_snapshot = _snapshot.inState(ConnectionState.none);
}
_subscribe();
}
}
@override
Widget build(BuildContext context) => widget.builder(context, _snapshot);
@override
void dispose() {
_unsubscribe();
super.dispose();
}
void _subscribe() {
if (widget.future != null) {
final Object callbackIdentity = Object();
_activeCallbackIdentity = callbackIdentity;
widget.future!.then<void>((T data) {
if (_activeCallbackIdentity == callbackIdentity) {
setState(() {
_snapshot = AsyncSnapshot<T>.withData(ConnectionState.done, data);
});
}
}, onError: (Object error, StackTrace stackTrace) {
if (_activeCallbackIdentity == callbackIdentity) {
setState(() {
_snapshot = AsyncSnapshot<T>.withError(
ConnectionState.done, error, stackTrace);
});
}
assert(() {
if (FutureBuilder.debugRethrowError) {
Future<Object>.error(error, stackTrace);
}
return true;
}());
});
if (widget.activeTime != null) {
_snapshot = _snapshot.inState(ConnectionState.active);
Future.delayed(widget.activeTime!).then((value) {
if (_activeCallbackIdentity == callbackIdentity &&
_snapshot.connectionState == ConnectionState.active) {
/// データがActiveの場合waitingに遷移する
setState(() {
_snapshot = _snapshot.inState(ConnectionState.waiting);
});
}
});
} else {
_snapshot = _snapshot.inState(ConnectionState.waiting);
}
}
}
void _unsubscribe() {
_activeCallbackIdentity = null;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment