質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Flutter

Flutterは、iOSとAndroidのアプリを同じコードで開発するためのフレームワークです。オープンソースで開発言語はDart。双方のプラットフォームにおける高度な実行パフォーマンスと開発効率を提供することを目的としています。

Dart

Dartは、Googleによって開発されたJavaScriptの代替となることを目的に作られた、ウェブ向けのプログラミング言語である。

Q&A

解決済

1回答

2115閲覧

FlutterError (setState() called after dispose(): により画面遷移がうまくいかない

Gento

総合スコア77

Flutter

Flutterは、iOSとAndroidのアプリを同じコードで開発するためのフレームワークです。オープンソースで開発言語はDart。双方のプラットフォームにおける高度な実行パフォーマンスと開発効率を提供することを目的としています。

Dart

Dartは、Googleによって開発されたJavaScriptの代替となることを目的に作られた、ウェブ向けのプログラミング言語である。

0グッド

0クリップ

投稿2022/10/02 13:34

解決したい問題

「サインイン」というボタンを押したらFirebaseの匿名認証でサインインし、TOP画面に遷移したいです。

しかし、画面の遷移自体は成功するのですが、TOP画面へ遷移した直後下記のようなエラーが発生します。。

console

1FlutterError (setState() called after dispose(): 2_IntroductionScreenState#b372c(lifecycle state: defunct, not mounted) This error 3happens if you call setState() on a State object for a widget that no longer 4appears in the widget tree (e.g., whose parent widget no longer includes the 5widget in its build). This error can occur when code calls setState() from a 6timer or an animation callback. The preferred solution is to cancel the timer or 7stop listening to the animation in the dispose() callback. Another solution is to 8check the "mounted" property of this object before calling setState() to ensure 9the object is still in the tree. This error might indicate a memory leak if 10setState() is being called because another object is retaining a reference to 11this State object after it has been removed from the tree. To avoid memory leaks, 12 consider breaking the reference to this object during dispose().)

該当のソースコード

dart:lib/screens/introduction/introduction_screen.dart

1import 'package:flutter/material.dart'; 2import 'package:lovedan/resources/auth_methods.dart'; 3import 'package:lovedan/responsive/mobile_screen_layout.dart'; 4import 'package:lovedan/responsive/responsive_layout.dart'; 5import 'package:lovedan/responsive/web_screen_layout.dart'; 6import 'package:lovedan/utils/utils.dart'; 7import 'package:lovedan/utils/colors.dart'; 8 9class IntroductionScreen extends StatefulWidget { 10 11 State<IntroductionScreen> createState() => _IntroductionScreenState(); 12} 13 14class _IntroductionScreenState extends State<IntroductionScreen> { 15 bool _isLoading = false; 16 17 18 void dispose() { 19 _isLoading = false; 20 super.dispose(); 21 } 22 23 void signInAnonymously() async { 24 // set loading to true 25 setState(() { 26 _isLoading = true; 27 }); 28 29 // signup user using our authmethodds 30 String res = await AuthMethods().signInAnonymously(); 31 // if string returned is sucess, user has been created 32 if (res == "success") { 33 setState(() { // ここでエラー 34 _isLoading = false; 35 }); 36 37 // navigate to the home screen 38 Navigator.of(context).pushReplacement(MaterialPageRoute( 39 builder: (context) => const ResponsiveLayout( 40 mobileScreenLayout: MobileScreenLayout(), 41 webScreenLayout: WebScreenLayout(), 42 ), 43 )); 44 } else { 45 setState(() { 46 _isLoading = false; 47 }); 48 // show the error 49 showSnackBar(context, res); 50 } 51 } 52 53 54 Widget build(BuildContext context) { 55 return Scaffold( 56 body: Center( 57 child: ElevatedButton( 58 child: !_isLoading 59 ? const Text('はじめる') 60 : const CircularProgressIndicator(color: primaryColor), 61 onPressed: signInAnonymously, 62 ), 63 ), 64 ); 65 } 66}

dart:lib/resources/auth_methods.dart

1 Future signInAnonymously() async { 2 String res = "エラーが発生しました。。。もう一度試してください。"; 3 try { 4 UserCredential userCredential = await _auth.signInAnonymously(); 5 model.User _user = model.User( 6 uid: userCredential.user!.uid, 7 createdAt: DateTime.now(), 8 watchingList: [], 9 ); 10 11 // adding user in our database 12 await _firestore 13 .collection('users') 14 .doc(userCredential.user!.uid) 15 .set(_user.toJson()); 16 res = "success"; 17 } catch (err) { 18 res = err.toString(); 19 print(res); 20 } 21 return res; 22 }

disposeされた後にsetState関数が呼ばれているからエラーになっている、というのはわかるのですが、、どうコードを書き換えれば良いでしょうか??

試したこと

https://blog.mrym.tv/2019/12/traps-on-calling-setstate-inside-initstate/

上記を参考に以下のようにコードを変えてみました。

dart:lib/screens/introduction/introduction_screen.dart

1 // signup user using our authmethodds 2 String res = await AuthMethods().signInAnonymously(); 3 // if string returned is sucess, user has been created 4 if (res == "success") { 5 if (mounted) { 6 setState(() { 7 _isLoading = false; 8 }); 9 }

すると以下のようにエラー内容が変わりました。。。

console

1FlutterError (This widget has been unmounted, so the State no longer has a context (and should be considered defunct). 2Consider canceling any active work during "dispose" or using the "mounted" getter to determine if the State is still active.)

ますます意味がわからなくなりました。。。。
何が起こっているのか、どなたかご教授いただけると幸いです🙏

参考にしたコード

https://github.com/RivaanRanawat/instagram-flutter-clone/blob/master/lib/screens/signup_screen.dart

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

同一の実装はできないのですが、似たような実装をして操作ミスっぽいことをしたら発生しました。
操作ミスとはCircularProgressIndicatorが表示中に再度ボタンをタップするです。

ちなみに、処理が完了するまでタップを我慢できれば問題ないはずですが、そこらあたりの操作についてはどうでしょうか。

対策は、以下の様に_isLoading中は処理から抜けるようにするです。

dart

1 void signInAnonymously() async { 2 if (_isLoading) { 3 return; 4 }

理由は、signInAnonymouslyの処理中にsignInAnonymouslyが呼び出され、1回目のsignInAnonymouslyの画面遷移が完了したのち2回目のsignInAnonymously内のsetStateが呼び出されただめだと思われます。

投稿2022/10/03 00:18

ta.fu

総合スコア1667

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問