在登录/注册时重新触发 FutureBuilder

问题描述

我目前被困在我希望是一个简单的问题上,我只是尝试了很多,以至于我可能再也看不到解决方案了。

我有一个登陆页面,通过未来检查用户是否有活动会话(解析后端)。 我设法提出成功的登录注册请求,只是屏幕没有改变,这意味着未来的构建器不会重建。当我热重载时一切正常,但我无法自动触发热重载。我使用 Riverpod 进行状态管理。 hasUserLogged() 方法由 AuthBase 类通过 Riverpod 提供。 我将 updatedUser 方法交给 AuthScreen 以在登录/注册时触发它,但它不会触发 FutureBuilder 的重建。 我认为从服务器获取 updatedUser 还会在下一步中为我提供用户是否验证了其电子邮件的信息,但这是后续问题(但我希望能在正确的方向上指出如何解决 4x4 用户矩阵:有令牌/无令牌和已验证/未验证的电子邮件并根据组合重定向到身份验证/验证电子邮件/主页..)

无论如何,现在 - 如何在 AuthScreen 中按下登录/注册按钮时触发 FutureBuilder 的重建?


class LandingPage2 extends StatefulWidget {
  @override
  _LandingPage2State createState() => _LandingPage2State();
}

class _LandingPage2State extends State<LandingPage2> {

  Future<ParseUser> _updateUser() async {
    final auth = context.read(authProvider);

    ParseUser currentUser = await ParseUser.currentUser() as ParseUser;

    if (currentUser != null) {
      ParseResponse update = await currentUser.getUpdatedUser();
      if (update.success) {
        currentUser = update.result as ParseUser;
        await auth.hasUserLogged();
        setState(() {
          return currentUser;
        });
      }
    }

    if (currentUser == null) {
      print('null User');
    }
  }
  

  
   /// Check if user session token is valid
   Future<bool> hasUserLogged() async {
     ParseUser currentUser = await ParseUser.currentUser() as ParseUser;
     // return false if no user is logged in
     if (currentUser == null) {
       return false;
     }
     //Validates that the user's session token is valid
     final ParseResponse parseResponse =
         await ParseUser.getCurrentUserFromServer(
             currentUser.get<String>('sessionToken'));
  
     if (!parseResponse.success) {
       print('invalid session. logout');
       //Invalid session. logout
       await currentUser.logout();
       return false;
     } else {
       print('login successfull');
       return true;
     }
   }

  @override
  Widget build(BuildContext context) {
    final auth = context.read(authProvider);

    return FutureBuilder<bool>(
      future: auth.hasUserLogged(),builder: (context,snapshot) {
        print('futurebuilder rebuild');
        switch (snapshot.connectionState) {
          case ConnectionState.none:
           case ConnectionState.waiting:
             return SplashScreen();
             break;
          default:
            if (snapshot.hasData && snapshot.data) {
              return HomePage();
            } else {
              return AuthScreen(_updateUser);
            }
        }
      },);
  }
}

非常感谢任何帮助,几个小时以来一直在挣扎,我的头脑无法理解为什么它不起作用:-/

解决方法

谢谢@Randal Schwartz,在我创建了一个 AuthNotifier 和 StateNotifierProvider 来管理用户状态并在 hasUserLogged() 方法中依赖该用户之后,'watch' 让它发生了。

如果有人也在挣扎 - 这就是工作版本:

import 'dart:async';

import 'package:app/screens/splash_screen.dart';
import 'package:app/services/top_level_providers.dart';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:parse_server_sdk_flutter/parse_server_sdk.dart';

import 'auth_screen.dart';
import 'home.dart';

class LandingPage2 extends ConsumerWidget {
  @override
  Widget build(BuildContext context,ScopedReader watch) {
    final auth = watch(authProvider);

    /// Check if user session token is valid
    Future<bool> hasUserLogged() async {
      print('hasUserLogged - Fired');

      /// watch current User state  -- Triggers rebuild after login!
      final authNotifier = watch(authNotifierProvider.state);
      final ParseUser currentUser = authNotifier;

      // return false if no user is logged in
      if (currentUser == null) {
        print('currentUserNULL');
        return false;
      }

      //Validates that the user's session token is valid
      final ParseResponse parseResponse =
          await ParseUser.getCurrentUserFromServer(
              currentUser.get<String>('sessionToken'));

      if (!parseResponse.success) {
        print('invalid session. logout');
        //Invalid session. Logout
        await currentUser.logout();
        return false;
      } else {
        print('login successfull');

        return true;
      }
    }

    return FutureBuilder<bool>(
      future: hasUserLogged(),builder: (context,snapshot) {
        print('futurebuilder rebuild');
        // print(snapshot.data);
        switch (snapshot.connectionState) {
          case ConnectionState.none:
          case ConnectionState.waiting:
            return SplashScreen();
            break;
          default:
            if (snapshot.hasData && snapshot.data) {
              /// Add Verify E-Mail Logic here - Another Future Builder??
              return HomePage();
            } else {
              // _updateUser();
              return AuthScreen();
            }
            break;
        }
      },);
  }
}

身份验证通知程序:

/// Auth Notifier Class
class AuthNotifier extends StateNotifier<ParseUser> {
  AuthNotifier(ParseUser state) : super(state);

  setCurrentUser(ParseUser user) {
    state = user;
  }

  void clearUser() {
    state = null;
  }
}

和提供者:

final authNotifierProvider = StateNotifierProvider((ref) {
  return AuthNotifier(null);
});

这是在收到登录/注册后的活动用户后触发的,从而触发 hasUserLogged 的​​重建。

authNotifier.setCurrentUser(user);

感谢您的帮助!确实花了我很多时间...不得不从 firebase 切换掉...