我目前面临一个问题,我将路由到身份验证保护视图作为我的默认路由。我的身份验证保护视图:
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
包含我的颤振应用程序的初始导航,并在开发过程中始终重置为索引零。
问题:此时如何避免不必要的重新加载?
到目前为止我测试的内容:
- 我
TabsScreenView
用 FutureBuilder / StreamBuilder 包装了我的命名路由并将其设置为默认路由(Flutter 中的 Route Guards) - 在用户更改时监听流
didComponentUpdate
并推送命名路由 - 上面提供的解决方案
如果您需要更多信息、代码、控制台打印或其他支持我,请给我留言。谢谢!