ChangeNotifierで非同期処理の結果を反映するときにエラーを出さないようにする
ChangeNotifierでページ単位の状態を管理しているとき,初期化などのタイミングに非同期で値を取得→notifyListeners()でUIに反映というパターンをよく使います.
そんなとき,愚直にChangeNotifier継承クラス(以下Controller)で取得→反映すると,↓みたいに怒られる場合があります.
https://gyazo.com/431ef93eeb9113e93ebe930226d60388
「disposeされたオブジェクトは呼び出せないよ!」というものです.例えば,ページの初期化時にAPIから値を取得するとして,取得している途中でNavigator.pop()などでページを離脱するとこうなります.
DartのFutureは仕様的にキャンセルができません.Streamであれば可能で,そのへんをうまく利用してなんやかんやすれば一応キャンセル判定などもできるようですが,ちょっとめんどくさいです.
どうすればいいか調べていたところ,provider作者のRemi氏によると,どうやら素直にそのControllerが生きているかどうかフラグで判定すればいい模様.
というわけで,これを意識せずできるようにmixin形式にしてみました.
code:cancelable_notify.dart
mixin CancelableNotify on ChangeNotifier {
bool _mounted = true;
@override
void notifyListeners() {
if (_mounted) super.notifyListeners();
}
@override
void dispose() {
_mounted = false;
super.dispose();
}
}
/// Usage:
/// class PageController extends ChangeNotifier with CancelableNotify {
/// PageController() {
/// initText();
/// }
///
/// String text = '';
///
/// void initText() async {
/// await Future.delayed(const Duration(milliseconds: 4000));
/// text = 'init';
/// notifyListeners();
/// }
/// }
使い方は,Usageにあるようにwith CancelableNotifyをつけるだけ!
これで怒られなくなりました🎉.
まぁFlutterは変に例外投げられても別にアプリが止まるわけでは無いのでアレですが…
投げられないのが第一なので.