android 如何提高Flutter Firebase应用的启动时间?

46scxncf  于 2023-05-21  发布在  Android
关注(0)|答案(2)|浏览(115)

bounty还有5天到期。回答此问题可获得+50声望奖励。Vasudev Soni正在寻找这个问题的更详细的答案:我想要一个详细的答案,告诉我代码的哪些部分需要修改。

我的应用程序已经在Play Store上上线了,但完全打开并进入主屏幕几乎需要15-20秒。我使用Firebase作为我的Flutter应用程序的后端。我已经包含了一步一步的代码,当我的应用程序启动时执行。

main.dart

AndroidNotificationChannel channel = const AndroidNotificationChannel(
  'high_importance_channel',
  'High Importance Notifications',
  description: 'This channel is used for high importance notifications',
  importance: Importance.max,
  playSound: true,
);

final FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin =
    FlutterLocalNotificationsPlugin();

Future<void> main() async {
  WidgetsFlutterBinding.ensureInitialized();

  // Initialize Firebase App
  await Firebase.initializeApp();

  // Activate Firebase App Check
  await FirebaseAppCheck.instance.activate(
    androidProvider: AndroidProvider.playIntegrity,
  );

  // Initialize Google Mobile Ads
  await MobileAds.instance.initialize();

  // Set preferred device orientation
  SystemChrome.setPreferredOrientations([
    DeviceOrientation.portraitUp,
    DeviceOrientation.portraitDown,
  ]);

  // Initialize Flutter Local Notifications Plugin
  // FirebaseMessaging.onBackgroundMessage(_firebaseMessagingBackgroundHandler);
  await flutterLocalNotificationsPlugin
      .resolvePlatformSpecificImplementation<
          AndroidFlutterLocalNotificationsPlugin>()
      ?.createNotificationChannel(channel);

  // Set foreground notification presentation options
  await FirebaseMessaging.instance.setForegroundNotificationPresentationOptions(
    alert: true,
    badge: true,
    sound: true,
  );

  runApp(
    MultiProvider(
      providers: [
        ChangeNotifierProvider(
          create: (_) => AppNavigationProvider(),
        ),
        ChangeNotifierProvider(
          create: (_) => SellerFormProvider(),
        ),
        ChangeNotifierProvider(
          create: (_) => LocationProvider(),
        ),
      ],
      child: const MyApp(),
    ),
  );
}

class MyApp extends StatefulWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  State<MyApp> createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  @override
  void initState() {
    super.initState();
    registerMessaging();
  }

  void registerMessaging() async {
    await compute(_registerMessaging, null);
  }

  static Future<void> _registerMessaging(void _) async {
    FirebaseMessaging.onMessage.listen((RemoteMessage message) {
      final RemoteNotification? notification = message.notification;
      final AndroidNotification? android = message.notification?.android;
      if (notification != null && android != null) {
        flutterLocalNotificationsPlugin.show(
          notification.hashCode,
          notification.title,
          notification.body,
          NotificationDetails(
            android: AndroidNotificationDetails(
              channel.id,
              channel.name,
              channelDescription: channel.description,
              playSound: true,
              importance: Importance.max,
              priority: Priority.high,
              color: greenColor,
              icon: '@mipmap/ic_launcher',
            ),
          ),
        );
      }
    });
  }

  @override
  Widget build(BuildContext context) {
    return GetMaterialApp(
      title: 'App name',
      color: blueColor,
      themeMode: ThemeMode.light,
      theme: ThemeData(fontFamily: 'Rubik'),
      debugShowCheckedModeBanner: false,
      home: const LoadingScreen(),
      onUnknownRoute: (RouteSettings settings) {
        return MaterialPageRoute(
          settings: settings,
          builder: (BuildContext context) => const ErrorScreen(),
        );
      },
    );
  }
}

loading_screen.dart

class LoadingScreen extends StatefulWidget {
  const LoadingScreen({Key? key}) : super(key: key);

  @override
  State<LoadingScreen> createState() => _LoadingScreenState();
}

class _LoadingScreenState extends State<LoadingScreen> {
  @override
  void initState() {
    super.initState();
    //check whether user is logged in or not. Then navigate her accordingly.
    FirebaseAuth.instance.authStateChanges().listen((User? user) {
      if (user != null) {
        Get.offAll(() => const MainScreen(selectedIndex: 0));
      } else {
        Get.offAll(() => const LandingScreen());
      }
    });
  }

  @override
  Widget build(BuildContext context) {
    return const Scaffold(
      backgroundColor: whiteColor,
      body: Center(
        child: CustomLoadingIndicator(),
      ),
    );
  }
}

main_screen.dart

class MainScreen extends StatefulWidget {
  final int selectedIndex;
  const MainScreen({super.key, required this.selectedIndex});

  @override
  State<MainScreen> createState() => _MainScreenState();
}

class _MainScreenState extends State<MainScreen> {
  final FirebaseServices _services = FirebaseServices();
  final User? user = FirebaseAuth.instance.currentUser;
  late StreamSubscription<ConnectivityResult> subscription;
  bool isDeviceConnected = false;
  bool isAlertSet = false;

  @override
  void initState() {
    super.initState();
    getConnectivity();
  }

  showNetworkError() {
    showModalBottomSheet(
      context: context,
      backgroundColor: transparentColor,
      isDismissible: false,
      enableDrag: false,
      isScrollControlled: false,
      builder: (context) {
        return SafeArea(
          child: Container(
            decoration: const BoxDecoration(
              borderRadius: BorderRadius.only(
                topLeft: Radius.circular(10),
                topRight: Radius.circular(10),
              ),
              color: whiteColor,
            ),
            padding: EdgeInsets.only(
              bottom: MediaQuery.of(context).viewInsets.bottom + 15,
              left: 15,
              right: 15,
              top: 15,
            ),
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.center,
              mainAxisSize: MainAxisSize.min,
              children: [
                Center(
                  child: Text(
                    'Network Connection Lost',
                    style: GoogleFonts.interTight(
                      fontSize: 20,
                      fontWeight: FontWeight.w600,
                    ),
                    textAlign: TextAlign.center,
                  ),
                ),
                const SizedBox(
                  height: 15,
                ),
                Image.asset(
                  'assets/no-network.png',
                  fit: BoxFit.contain,
                  semanticLabel: 'no network connection',
                  width: MediaQuery.of(context).size.width * 0.8,
                  height: MediaQuery.of(context).size.height * 0.2,
                ),
                const SizedBox(
                  height: 15,
                ),
                Container(
                  padding: const EdgeInsets.all(15),
                  width: double.infinity,
                  decoration: BoxDecoration(
                    borderRadius: BorderRadius.circular(10),
                    color: greyColor,
                  ),
                  child: Text(
                    'Please check your internet connection',
                    textAlign: TextAlign.center,
                    maxLines: 2,
                    softWrap: true,
                    overflow: TextOverflow.ellipsis,
                    style: GoogleFonts.interTight(
                      fontSize: 15,
                      fontWeight: FontWeight.w500,
                    ),
                  ),
                ),
                const SizedBox(
                  height: 10,
                ),
                CustomButtonWithoutIcon(
                  text: 'Re-Connect',
                  onPressed: () async {
                    Get.back();
                    setState(() {
                      isAlertSet = false;
                    });
                    isDeviceConnected =
                        await InternetConnectionChecker().hasConnection;
                    if (!isDeviceConnected) {
                      showNetworkError();
                      setState(() {
                        isAlertSet = true;
                      });
                    }
                  },
                  borderColor: redColor,
                  bgColor: redColor,
                  textIconColor: whiteColor,
                ),
              ],
            ),
          ),
        );
      },
    );
  }

  Future<void> getConnectivity() async {
    await for (final _ in Connectivity().onConnectivityChanged) {
      isDeviceConnected = await InternetConnectionChecker().hasConnection;
      if (!isDeviceConnected && !isAlertSet) {
        showNetworkError();
        setState(() => isAlertSet = true);
      }
    }
  }

  Future<void> onSellButtonClicked() async {
    final userData = await _services.getCurrentUserData();
    if (userData['location'] != null) {
      Get.to(
        () => const SellerCategoriesListScreen(),
      );
    } else {
      Get.to(() => const LocationScreen(isOpenedFromSellButton: true));
      showSnackBar(
        content: 'Please set your location to sell products',
        color: redColor,
      );
    }
  }

  @override
  void dispose() {
    subscription.cancel();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Consumer2<LocationProvider, AppNavigationProvider>(
      builder: (context, locationProv, mainProv, child) {
        final int selectedIndex = mainProv.currentPageIndex;

        final List<Widget> pages = [
          HomeScreen(
            locationData: locationProv.locationData,
          ),
          const MyChatsScreen(),
          const MyFavoritesScreen(),
          const MyProfileScreen(),
        ];

        const List<IconData> iconsList = [
          MdiIcons.homeOutline,
          MdiIcons.chatOutline,
          MdiIcons.heartOutline,
          MdiIcons.accountCircleOutline,
        ];

        const List<IconData> selectedIconsList = [
          MdiIcons.home,
          MdiIcons.chat,
          MdiIcons.heart,
          MdiIcons.accountCircle,
        ];

        const List<String> titlesList = [
          'Explore',
          'Chats',
          'Favorites',
          'Account',
        ];

        void onItemTapped(int index) {
          mainProv.switchToPage(index);
        }

        void onFloatingActionButtonPressed() {
          if (!user!.emailVerified &&
              user!.providerData[0].providerId == 'password') {
            Get.to(() => const EmailVerificationScreen());
          } else {
            onSellButtonClicked();
          }
        }

        return Scaffold(
          backgroundColor: whiteColor,
          body: IndexedStack(
            index: selectedIndex,
            children: pages,
          ),
          floatingActionButton: FloatingActionButton(
            backgroundColor: blueColor,
            elevation: 0,
            tooltip: 'List a product',
            enableFeedback: true,
            onPressed: onFloatingActionButtonPressed,
            child: const Center(
              child: Icon(
                MdiIcons.plus,
                size: 35,
              ),
            ),
          ),
          floatingActionButtonLocation:
              FloatingActionButtonLocation.centerDocked,
          bottomNavigationBar: AnimatedBottomNavigationBar.builder(
            onTap: onItemTapped,
            gapLocation: GapLocation.center,
            activeIndex: selectedIndex,
            backgroundColor: greyColor,
            elevation: 5,
            height: 55,
            leftCornerRadius: 10,
            rightCornerRadius: 10,
            notchSmoothness: NotchSmoothness.defaultEdge,
            splashColor: transparentColor,
            itemCount: pages.length,
            tabBuilder: (index, isActive) {
              return Column(
                mainAxisSize: MainAxisSize.min,
                mainAxisAlignment: MainAxisAlignment.center,
                children: [
                  Icon(
                    selectedIndex == index
                        ? selectedIconsList[index]
                        : iconsList[index],
                    size: 24,
                    color: blackColor,
                  ),
                  AutoSizeText(
                    titlesList[index],
                    maxLines: 1,
                    style: TextStyle(
                      fontSize: 12,
                      fontWeight: selectedIndex == index
                          ? FontWeight.w600
                          : FontWeight.w500,
                      color: blackColor,
                    ),
                  )
                ],
              );
            },
          ),
        );
      },
    );
  }
}

home_screen.dart

class HomeScreen extends StatefulWidget {
  final LocationData? locationData;
  const HomeScreen({
    super.key,
    this.locationData,
  });

  @override
  State<HomeScreen> createState() => _HomeScreenState();
}

class _HomeScreenState extends State<HomeScreen>
    with SingleTickerProviderStateMixin {
  late TabController tabBarController;
  final _services = FirebaseServices();
  final User? user = FirebaseAuth.instance.currentUser;
  String area = '';
  String city = '';
  String state = '';
  bool isLocationEmpty = false;
  bool isLoading = true;

  late DateTime currentBackPressTime;

  @override
  void initState() {
    super.initState();
    tabBarController = TabController(
      length: 3,
      vsync: this,
    );
    _getCurrentUserData();
  }

  void _getCurrentUserData() async {
    final value = await _services.getCurrentUserData();
    if (value['location'] == null) {
      _getEmptyLocationUI();
    } else {
      _getAddressToUI(value);
    }
    setState(() {
      isLoading = false;
    });
  }

  void _getAddressToUI(DocumentSnapshot<Object?> value) {
    if (mounted) {
      setState(() {
        area = value['location']['area'];
        city = value['location']['city'];
        state = value['location']['state'];
      });
    }
  }

  _getEmptyLocationUI() {
    if (mounted) {
      setState(() {
        isLocationEmpty = true;
        tabBarController.index = 1;
      });
    }
  }

  @override
  void dispose() {
    tabBarController.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: whiteColor,
      body: AppBody(),
      );
  }
}

我已经尝试了我所知道的一切,但发射时间仍然没有缩短。将时间减少5-10%将对我的应用程序的用户留存率产生巨大影响。
请帮帮我

s71maibg

s71maibg1#

有三个步骤你应该考虑,以减少加载时间。
1.找出哪些调用是在初始加载时必须出现的(即用户在第一个屏幕上看到的内容),并将其余的调用移动到lateInit函数中。
1.尽可能使用异步函数,以免延迟进程。
1.第一次加载可能会更长,但之后你可以“缓存”特定的东西,并加快加载时间,为下次。
在您的情况下,您可能有一个“轻”主屏幕,它首先加载只需要的信息。Binance应用程序是一个很好的例子,它加载主页,然后您可以获得帐户的值或其他比率。

e37o9pze

e37o9pze2#

我的主屏幕很快就打开了,但在那之后,数据从firebase以列表视图、标签视图和网格视图加载。这种数据加载占用了大部分时间。
1.您是否正在从数据库加载所有数据?如果是,则必须使用跳过/限制
1.初始化Google AdMob应该是unawaited,因为应用加载不应该取决于广告是否加载。

相关问题