微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

Flutter 使用 Flutter-fire 身份验证保护器保护路由并避免不必要的重建

如何解决Flutter 使用 Flutter-fire 身份验证保护器保护路由并避免不必要的重建

我目前面临一个问题,我将路由到身份验证防护视图作为我的认路由。 我的身份验证守卫视图:

import 'package:Flutter/material.dart';
import 'package:provider/provider.dart';

import '../models/user.dart';
import '../services/services.module.dart';
import '../widgets/common/async_stream.dart';
import 'landing_screen/landing_screen.dart';
import 'tabs_screen/tab_screen.dart';

/// The [ViewAuthGuard] decides whether to display the [LandingScreenView] or the [TabsScreenView].
class ViewAuthGuard extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    print('ViewAuthGuard build called: $context');
    FirebaseAuthService authService = Provider.of<AuthService>(context,listen: false);

    return AsyncStreamWidget<User>(
      stream: authService.onAuthStateChanged,child: (User user) => TabsScreenView(),emptyWidget: LandingScreenView(),loadingWidget: null,errorWidget: null,);
  }
}

还有我的AsyncStreamWidget

import 'package:Flutter/material.dart';

import '../../../models/base_model.dart';
import '../../error/future_error.dart';
import '../../loading.dart';

class AsyncStreamWidget<T extends BaseModel> extends StatelessWidget {
  final Stream<T> stream;
  final T initialData;

  Widget _loading;
  Widget _empty;
  Widget Function(Object) _error;
  Widget Function(T) child;

  AsyncStreamWidget({
    @required this.stream,@required this.child,this.initialData,Widget loadingWidget,Widget emptyWidget,Widget Function(Object) errorWidget,}) {
    if (loadingWidget == null) {
      _loading = Loading();
    } else {
      _loading = loadingWidget;
    }

    if (errorWidget == null) {
      _error = (Object error) => FutureErrorWidget(error: error);
    } else {
      _error = errorWidget;
    }

    if (emptyWidget == null) {
      _empty = Center(child: Text('No data available.'));
    } else {
      _empty = emptyWidget;
    }
  }

  @override
  Widget build(BuildContext context) {
    return StreamBuilder<T>(
      initialData: initialData,stream: stream,builder: (_,AsyncSnapshot<T> snapshot) {
        switch (snapshot.connectionState) {
          case ConnectionState.waiting:
            return _loading;
            break;
          case ConnectionState.active: // check if different behavior is needed for active and done
          case ConnectionState.done:
            // error state
            if (snapshot.hasError) {
              // todo more throughout error checking and specialized error widget
              return _error(snapshot.error);
            }

            // data state
            if (snapshot.hasData) {
              T data = snapshot.data;
              return child(data);
            }

            // empty state
            return _empty;
          case ConnectionState.none:
          default:
            print('E: Received Future [$stream] was null or else.');
            return _error('UnkNown error.');
        }
      },);
  }
}

FirebaseAuthService 包裹了 auth.FirebaseAuth.instance。我的流构造如下:

User _userFromFirebase(auth.User user) {
  if (user == null) {
    return null;
  }
  return User(
    uid: user.uid,email: user.email,displayName: user.displayName,photoUrl: user.photoURL,);
}

@override
Stream<User> get onAuthStateChanged => _firebaseAuth.authStateChanges().map(_userFromFirebase);

我目前提供高于 ViewAuthGuard 的所有服务。

我用 ThemeProvider ChangeNotifier 包装了我的 Material 应用程序(以防万一这可能是一个问题)。

我的问题是 ViewAuthGuard 下的所有小部件都被重建并且它们的状态被重置。这是我在开发时发生的。当发生热重载时,所有子项都将重建。 TabsScreenView 包含我的 Flutter 应用程序的初始导航,并在开发过程中始终重置为索引零。

问题:此时如何避免不必要的重新加载?

我目前测试的内容

  • 我使用 FutureBuilder / StreamBuilder 包装了 TabsScreenView 的命名路由,并将其设置为认路由 (Route Guards in Flutter)
  • 收听 didComponentUpdate 中的流并在用户更改时推送命名路由
  • 上面提供的解决方

如果您需要更多信息、代码、控制台打印或其他支持我,请给我留言。谢谢!

解决方法

我能够自己修复它。对于任何感兴趣的人,这是过程:

stream 是决定 AsyncStreamWidget 是否重建其子项的枢轴元素。因此,我确实通过打印其 stream 属性来检查 hashCode 是否在热重新加载时发生了变化(是的,它确实发生了变化)。

随后,我确实将 ViewAuthGuard 更改为 StatefulWidget,并使用 didChangeDependencies 方法将 stream 存储在状态中。

(我还开始在 initState 方法中实例化小部件并将它们存储在状态中,以便它们只创建一次。)


EDIT 而且我应该提到我的 ViewAuthGuard 没有依赖项。所以不会因为依赖关系的改变而重建。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。