2

ユーザー登録が機能するアプリがあり、ユーザープロバイダーを使用すると、登録中にユーザーを設定し、次の画面で問題なく取得できます。私が問題を抱えているのは、アプリの起動時に保存されている現在ログインしているユーザーを設定し、以下のアサーションをスローせずに登録プロセスを実行するのではなく、ダッシュボードに進む機能を適切に実装しようとしていることです。

問題なくユーザーを取得できSharedPreferencesますが、ダッシュボード画面が読み込まれたときにアクセスできるように、プロバイダーでこのユーザーを適切に設定する方法がわかりません。以下は私のmain()関数と MyApp クラスです。

void main() {
  WidgetsFlutterBinding.ensureInitialized();

  runApp(MultiProvider(
    providers: [
      ChangeNotifierProvider(create: (context) => AuthProvider()),
      ChangeNotifierProvider(create: (context) => UserProvider()),
    ],
    child: MyApp(),
  ));
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    Future<User> getUserData() => UserPreferences().getUser();

    return MaterialApp(
        title: 'My App',
        theme: ThemeData(
          primarySwatch: Colors.red,
          accentColor: Colors.black,
          visualDensity: VisualDensity.adaptivePlatformDensity,
        ),
        home: FutureBuilder(
            future: getUserData().then((value) => {
                  Provider.of<UserProvider>(context, listen: false)
                      .setUser(value)
                }),
            builder: (context, snapshot) {
              switch (snapshot.connectionState) {
                case ConnectionState.none:
                case ConnectionState.waiting:
                  return CircularProgressIndicator();
                default:
                  if (snapshot.hasError)
                    return Text('Error: ${snapshot.error}');
                  else if (snapshot.data.token == null)
                    return Login();
                  else if (snapshot.data.token != null) {
                    return Dashboard();
                  } else {
                    UserPreferences().removeUser();
                    return Login();
                  }
              }
            }),
        routes: {
          '/dashboard': (context) => Dashboard(),
          '/login': (context) => Login(),
          '/register': (context) => Register(),
          '/username': (context) => Username(),
        });
  }
}

FutureBuilder で、ユーザーを設定する呼び出しで then を連鎖しようとしましたがgetUserData()、もちろんこれは次のアサーションを返します:

════════ Exception caught by foundation library ════════════════════════════════
The following assertion was thrown while dispatching notifications for UserProvider:
setState() or markNeedsBuild() called during build.

This _InheritedProviderScope<UserProvider> widget cannot be marked as needing to build because the framework is already in the process of building widgets.  A widget can be marked as needing to be built during the build phase only if one of its ancestors is currently building. This exception is allowed because the framework builds parent widgets before children, which means a dirty descendant will always be built. Otherwise, the framework might not visit this widget during this build phase.

私が読んだことから、これはnotifyListeners()、ユーザープロバイダーに を呼び出す呼び出しがあるためmarkNeedsBuild()です。そうは言っても、私は物事を動かそうとオンラインでいくつかの提案を試みましたが、これを実装するためのベストプラクティスとベストな方法が何であるかを理解できません.

ユーザー プロバイダー:

class UserProvider with ChangeNotifier {
  User _user = new User();

  User get user => _user;

  void setUser(User user) {
    _user = user;
    notifyListeners();
  }
}

上記のアサーションに遭遇せずに誰かがすでにログインしている場合、アプリのロード時にユーザーを適切に設定するにはどうすればよいですか? ありがとう!

4

2 に答える 2