使用 Riverpod + StateNotifier 但我认为其他提供商也存在同样的问题。
我有一个身份验证 StateNotifier 类和 StateNotifierProvider 并将 MaterialApp 小部件包装到 Riverpod Consumer 中,以在用户不再经过身份验证时重建完整的应用程序/小部件树。
一旦我使用 pushReplacementNamed 导航到第三页并更新 authenticationStateNotifierProvider 的状态,我可以看到包装应用程序的消费者的构建方法被触发并且状态被更新(打印(状态))但主页和小部件树没有重建。
带有问题的 3 个屏幕的示例应用程序:
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/all.dart';
void main() {
runApp(ProviderScope(child: MyApp()));
}
class MyApp extends ConsumerWidget {
@override
Widget build(BuildContext context, ScopedReader watch) {
final state = watch(authenticationNotifier.state);
print(state);
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: state is Unauthenticated ? LoginScreen() : HomeScreen(),
onGenerateRoute: (RouteSettings settings) {
if (settings.name == '/second')
return MaterialPageRoute(builder: (_) => SecondScreen());
else
return MaterialPageRoute(builder: (_) => HomeScreen());
},
);
}
}
class HomeScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('HomeScreen'),
),
body: Column(
children: [
MaterialButton(
child: Text('Logout'),
onPressed: () => context.read(authenticationNotifier).toggle(),
),
MaterialButton(
child: Text('Second'),
onPressed: () => Navigator.pushReplacementNamed(
context,
'/second',
),
),
],
),
);
}
}
class SecondScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('SecondScreen'),
),
body: MaterialButton(
child: Text('Logout'),
onPressed: () => context.read(authenticationNotifier).toggle(),
),
);
}
}
class LoginScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('LoginScreen'),
),
body: MaterialButton(
child: Text('Login'),
onPressed: () => context.read(authenticationNotifier).toggle(),
),
);
}
}
// Controller.
final authenticationNotifier =
StateNotifierProvider((ref) => AuthenticationNotifier());
class AuthenticationNotifier extends StateNotifier<AuthenticationState> {
AuthenticationNotifier() : super(Unauthenticated());
void toggle() {
state = state is Unauthenticated ? Authenticated() : Unauthenticated();
}
}
// State.
abstract class AuthenticationState {}
class Authenticated extends AuthenticationState {}
class Unauthenticated extends AuthenticationState {}
如果您测试应用程序,您将看到登录和主页之间的状态管理与代码的预期一样,但是一旦您从主页导航到第二个屏幕并按下注销按钮,应用程序上的状态就会改变,但是小部件树未更新。