材料app重建当家庭小部件调用构建功能时

发布于 2025-01-29 09:31:54 字数 4708 浏览 6 评论 0原文

我的应用程序的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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文