使用Flutter-Fire身份验证守卫来保护安全路由,并避免不必要的重建。
使用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';
/// [ViewAuthGuard]决定显示[LandingScreenView]还是[TabsScreenView]。
class ViewAuthGuard extends StatelessWidget {
@override
Widget build(BuildContext context) {
print('ViewAuthGuard build called: $context');
FirebaseAuthService authService = Provider.of
return AsyncStreamWidget
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
final 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
initialData: initialData,
stream: stream,
builder: (_, AsyncSnapshot
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
我目前在`ViewAuthGuard`之上提供了所有的服务。
我用ThemeProvider ChangeNotifier包装了我的Material App(如果这可能是一个问题)。
我的问题是,`ViewAuthGuard`之下的所有小部件都会重新构建,并且它们的状态会被重置。这在我开发时发生。当进行热重载时,所有的子部件都会重新构建。`TabsScreenView`包含我Flutter应用程序的初始导航,并且在开发过程中始终重置为索引零。
问题:我如何避免这个时候不必要的重新加载?
我测试了以下内容:
- 使用FutureBuilder / StreamBuilder包装了我的命名路由`TabsScreenView`,并将其设置为默认路由([Flutter中的路由守卫](https://stackoverflow.com/questions/51027858/route-guards-in-flutter))
- 在`didComponentUpdate`中监听流,并在用户更改时推送命名路由
- 上面提供的解决方案
如果您需要更多信息,代码,控制台打印或其他支持,请给我留言。谢谢!