材料app重建当家庭小部件调用构建功能时
我的应用程序的myApp
窗口小部件,返回材料应用
(几乎在每个flutter应用程序中完成),每当home> home> home
widget称为build>时,都会重新构建。我需要知道为什么会发生这种情况,因为它大大降低了我的应用程序的性能。
我使用StreamProvider( riverpod 主页,landingpage
或加载屏幕(出于历史原因,pseudosplashscreen
),具体取决于用户是否登录,还是流等待。
我的main.dart
包含,除其他外:
Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();
FirebaseMessaging.instance.unsubscribeFromTopic('allUsers');
runApp(const ProviderScope(child: MyApp()));
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
debugPrint("Returning MaterialApp");
return MaterialApp(
title: 'MyApp',
localizationsDelegates: AppLocalizations.localizationsDelegates,
supportedLocales: AppLocalizations.supportedLocales,
debugShowCheckedModeBanner: false,
theme: themeDataLight(),
darkTheme: themeDataDark(),
home: const ReDirector(),
);
}
}
class ReDirector extends ConsumerWidget {
const ReDirector({Key? key}) : super(key: key);
static const LandingPage landingPage = LandingPage();
static const PseudoSplashScreen pseudoSplashScreen = PseudoSplashScreen();
@override
Widget build(BuildContext context, WidgetRef ref) {
debugPrint("Building Redirector");
return ref.watch(authStreamProvider).when(
data: (data) {
debugPrint(data.toString());
if (data != null && data == AuthResultStatus.successful) {
debugPrint("Returning Homepage");
return Container(
width: double.infinity,
height: double.infinity,
color: Colors.blue,
);
} else {
debugPrint("AuthStreamProvider returned $data");
// When logging in, it is set to true. Hence, set it to false to prevent
// the isInAsync overlay from showing when logging out.
ref.read(landingPageProvider).isInAsync = false;
return landingPage;
}
},
error: (e, tb) {
debugPrint("Error in the AuthChecker");
debugPrint("$e\n$tb");
// When logging in, it is set to true. Hence, set it to false to prevent
// the isInAsync overlay from showing on error
ref.read(landingPageProvider).isInAsync = false;
return landingPage;
},
loading: () {
debugPrint("Returning PseudoSplashScreen");
return pseudoSplashScreen;
},
);
}
}
流是从firebaseauth.instance.authstatatechanges
,但已扩展以检查用户上的一些额外详细信息:
final authStreamProvider = StreamProvider.autoDispose<AuthResultStatus?>((ref) {
return FirebaseAuth.instance
.authStateChanges()
.asyncExpand((User? user) async* {
AuthResultStatus? result;
if (user != null) {
final IdTokenResult idTokenResult = await user.getIdTokenResult();
if (user.emailVerified && idTokenResult.claims!['approved'] == true) {
ref.read(userDataProvider).initialize(user, idTokenResult.claims!);
result = AuthResultStatus.successful;
} else {
result = AuthResultStatus.undefined;
}
}
debugPrint("AuthStreamProvider is yielding $result");
yield result;
});
});
where > AuthResultStatus
是枚举。现在,我希望在流量加载时,显示了伪PlaSplashScreen,并且当流触发authresultStatus.successful
时,显示了homepage
。确实发生了什么,但是以某种方式我的redirector
在显示主页后大约一秒钟重建。实际上,再次调用myApp
的构建函数!关于代码中的调试打印机,控制台显示了以下内容:
I/flutter (22428): Returning MaterialApp
I/flutter (22428): Building Redirector
I/flutter (22428): Returning PseudoSplashScreen
I/flutter (22428): Creating new userdatamodel
I/flutter (22428): CURRENTUSER: Wessel van Dam
I/flutter (22428): AuthStreamProvider is yielding AuthResultStatus.successful
I/flutter (22428): Building Redirector
I/flutter (22428): AuthResultStatus.successful
I/flutter (22428): Returning Homepage
I/flutter (22428): Returning MaterialApp
I/flutter (22428): Building Redirector
I/flutter (22428): AuthResultStatus.successful
I/flutter (22428): Returning Homepage
请注意,重建导演的重建不是由于流的新射击事件引起的,因为那时您会期望返回成功的ARS
的另一幅印刷品。但是,重建重建导演非常烦人,因为构建主页是一个非常激烈的过程。这种重建会导致屏幕闪烁。谁能告诉我为什么在此序列中再次调用重定向器的构建功能?如果可以防止这种情况,我的应用程序的用户体验将得到很大改善。
My app's MyApp
widget, which returns MaterialApp
(as done in virtually every Flutter app) is rebuild whenever the build function on the home
widget is called. I need to know why this happens, as it greatly reduces the performance of my app.
I use a StreamProvider (the Riverpod implementation of StreamBuilder) to either show my app's HomePage
, LandingPage
or loading screen (called PseudoSplashScreen
for historical reasons), depending on whether a user is logged in or not, or whether the stream is waiting.
My main.dart
contains, among other things:
Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();
FirebaseMessaging.instance.unsubscribeFromTopic('allUsers');
runApp(const ProviderScope(child: MyApp()));
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
debugPrint("Returning MaterialApp");
return MaterialApp(
title: 'MyApp',
localizationsDelegates: AppLocalizations.localizationsDelegates,
supportedLocales: AppLocalizations.supportedLocales,
debugShowCheckedModeBanner: false,
theme: themeDataLight(),
darkTheme: themeDataDark(),
home: const ReDirector(),
);
}
}
class ReDirector extends ConsumerWidget {
const ReDirector({Key? key}) : super(key: key);
static const LandingPage landingPage = LandingPage();
static const PseudoSplashScreen pseudoSplashScreen = PseudoSplashScreen();
@override
Widget build(BuildContext context, WidgetRef ref) {
debugPrint("Building Redirector");
return ref.watch(authStreamProvider).when(
data: (data) {
debugPrint(data.toString());
if (data != null && data == AuthResultStatus.successful) {
debugPrint("Returning Homepage");
return Container(
width: double.infinity,
height: double.infinity,
color: Colors.blue,
);
} else {
debugPrint("AuthStreamProvider returned $data");
// When logging in, it is set to true. Hence, set it to false to prevent
// the isInAsync overlay from showing when logging out.
ref.read(landingPageProvider).isInAsync = false;
return landingPage;
}
},
error: (e, tb) {
debugPrint("Error in the AuthChecker");
debugPrint("$e\n$tb");
// When logging in, it is set to true. Hence, set it to false to prevent
// the isInAsync overlay from showing on error
ref.read(landingPageProvider).isInAsync = false;
return landingPage;
},
loading: () {
debugPrint("Returning PseudoSplashScreen");
return pseudoSplashScreen;
},
);
}
}
The Stream is derived from FirebaseAuth.instance.authStateChanges
but is expanded to check some extra details on the user:
final authStreamProvider = StreamProvider.autoDispose<AuthResultStatus?>((ref) {
return FirebaseAuth.instance
.authStateChanges()
.asyncExpand((User? user) async* {
AuthResultStatus? result;
if (user != null) {
final IdTokenResult idTokenResult = await user.getIdTokenResult();
if (user.emailVerified && idTokenResult.claims!['approved'] == true) {
ref.read(userDataProvider).initialize(user, idTokenResult.claims!);
result = AuthResultStatus.successful;
} else {
result = AuthResultStatus.undefined;
}
}
debugPrint("AuthStreamProvider is yielding $result");
yield result;
});
});
Where AuthResultStatus
is an enum. Now I would expect that while the stream is loading, the PseudoSplashScreen is shown, and when the Stream fires an AuthResultStatus.successful
, the HomePage
is shown. This is indeed what happens, but somehow my Redirector
is rebuild about a second after the HomePage is shown. In fact, the build function of MyApp
is called again! Regarding the debugPrints in the code, the console shows this:
I/flutter (22428): Returning MaterialApp
I/flutter (22428): Building Redirector
I/flutter (22428): Returning PseudoSplashScreen
I/flutter (22428): Creating new userdatamodel
I/flutter (22428): CURRENTUSER: Wessel van Dam
I/flutter (22428): AuthStreamProvider is yielding AuthResultStatus.successful
I/flutter (22428): Building Redirector
I/flutter (22428): AuthResultStatus.successful
I/flutter (22428): Returning Homepage
I/flutter (22428): Returning MaterialApp
I/flutter (22428): Building Redirector
I/flutter (22428): AuthResultStatus.successful
I/flutter (22428): Returning Homepage
Note that the rebuilding of the Redirector is not due to a new firing event of the Stream, because then you would expect another print of Returning successful ARS
. However, this rebuild of the Redirector is pretty annoying as building the HomePage is a pretty intense process. This rebuild causes a the screen to flicker. Could anyone tell me why the Redirector's build function is called again in this sequence? If that can be prevented, the user experience for my app would be greatly improved.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论