如何用Flutter FutureBuilder加载多份大JSON数据并自定义加载动画?
我来帮你搞定这个Flutter启动页的需求——既要显示全屏GIF动画,又要后台加载两个大JSON数据,完成后跳转页面,还要替换默认的圆形进度指示器对吧?直接上干货,一步步来实现:
实现方案:启动页全屏GIF + 多JSON后台加载 + 页面跳转
一、核心思路梳理
先把关键逻辑理清楚:
- 启动页用全屏GIF占满屏幕,同时并行请求两个JSON接口(比逐个请求效率更高)
- 用
Future.wait()批量处理异步任务,等所有请求完成后再跳转页面 - 跳转时用
Navigator.pushReplacement(),避免用户返回时回到启动页 - 把默认的
CircularProgressIndicator直接换成本地/网络GIF资源
二、代码分步实现
1. 先准备资源配置
把你的GIF动画放到项目的assets文件夹里,然后在pubspec.yaml中配置资源路径:
flutter: assets: - assets/loading_screen.gif # 替换成你的GIF文件名
2. main.dart 启动页核心代码
这里用StatefulWidget管理加载状态,后台并行请求两个JSON,完成后自动跳转:
import 'package:flutter/material.dart'; import 'dart:convert'; import 'package:http/http.dart' as http; import 'landing.dart'; void main() => runApp(const MyApp()); class MyApp extends StatelessWidget { const MyApp({super.key}); @override Widget build(BuildContext context) { return MaterialApp( title: 'Demo App', theme: ThemeData(primarySwatch: Colors.blue), home: const SplashScreen(), ); } } class SplashScreen extends StatefulWidget { const SplashScreen({super.key}); @override State<SplashScreen> createState() => _SplashScreenState(); } class _SplashScreenState extends State<SplashScreen> { // 存储两个JSON的解析结果 late Map<String, dynamic> jsonData1; late Map<String, dynamic> jsonData2; @override void initState() { super.initState(); // 页面初始化时就开始加载数据并准备跳转 _loadDataAndNavigate(); } // 并行加载两个JSON接口 Future<void> _loadDataAndNavigate() async { try { // 同时发起两个网络请求,等待全部完成 final responses = await Future.wait([ http.get(Uri.parse('https://your-first-api-url.com')), http.get(Uri.parse('https://your-second-api-url.com')), ]); // 解析两个JSON数据 jsonData1 = json.decode(responses[0].body); jsonData2 = json.decode(responses[1].body); // 确保Widget还在挂载状态,再执行跳转 if (!mounted) return; Navigator.pushReplacement( context, MaterialPageRoute( builder: (context) => LandingPage(data1: jsonData1, data2: jsonData2), ), ); } catch (e) { // 处理加载失败的情况,比如弹出错误提示 if (!mounted) return; ScaffoldMessenger.of(context).showSnackBar( SnackBar(content: Text('数据加载失败:$e')), ); } } @override Widget build(BuildContext context) { return Scaffold( body: Center( // 全屏GIF,替换默认的CircularProgressIndicator child: Image.asset( 'assets/loading_screen.gif', fit: BoxFit.cover, width: double.infinity, height: double.infinity, ), ), ); } }
3. landing.dart 着陆页代码
接收启动页传递的JSON数据,展示链接,点击登录按钮跳转:
import 'package:flutter/material.dart'; import 'login.dart'; class LandingPage extends StatelessWidget { final Map<String, dynamic> data1; final Map<String, dynamic> data2; const LandingPage({super.key, required this.data1, required this.data2}); @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: const Text('着陆页')), body: Padding( padding: const EdgeInsets.all(16.0), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ const Text('已加载的数据链接:', style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold)), const SizedBox(height: 12), // 根据你的JSON结构调整展示内容 Text('数据1链接:${data1['detail_link']}'), Text('数据2链接:${data2['detail_link']}'), const SizedBox(height: 30), ElevatedButton( onPressed: () { // 跳转至登录页 Navigator.push( context, MaterialPageRoute(builder: (context) => const LoginPage()), ); }, child: const Text('登录查看详情'), ), ], ), ), ); } }
4. login.dart 登录页代码
登录成功后跳转至首页:
import 'package:flutter/material.dart'; import 'home.dart'; class LoginPage extends StatefulWidget { const LoginPage({super.key}); @override State<LoginPage> createState() => _LoginPageState(); } class _LoginPageState extends State<LoginPage> { final _usernameController = TextEditingController(); final _passwordController = TextEditingController(); Future<void> _handleLogin() async { // 这里替换成你的真实登录逻辑,比如调用登录API await Future.delayed(const Duration(seconds: 1)); // 登录成功后跳转首页,移除登录页 if (!mounted) return; Navigator.pushReplacement( context, MaterialPageRoute(builder: (context) => const HomePage()), ); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: const Text('登录')), body: Padding( padding: const EdgeInsets.all(16.0), child: Column( children: [ TextField( controller: _usernameController, decoration: const InputDecoration(labelText: '用户名'), ), TextField( controller: _passwordController, decoration: const InputDecoration(labelText: '密码'), obscureText: true, ), const SizedBox(height: 20), ElevatedButton( onPressed: _handleLogin, child: const Text('登录'), ), ], ), ), ); } }
5. home.dart 首页示例代码
import 'package:flutter/material.dart'; class HomePage extends StatelessWidget { const HomePage({super.key}); @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: const Text('首页')), body: const Center(child: Text('登录成功!欢迎查看详情')), ); } }
三、关键知识点说明
Future.wait():专门用来批量处理异步任务,只有当所有任务都完成时才会继续执行,完美适配你加载多个JSON的需求Navigator.pushReplacement():跳转后会移除当前页面(比如启动页、登录页),符合这类过渡页面的逻辑,避免用户误返回- 全屏GIF实现:用
Image.asset()配合fit: BoxFit.cover+宽高double.infinity,就能实现完全覆盖屏幕的效果,直接替代默认进度指示器 mounted判断:异步操作完成后一定要先判断Widget是否还在挂载状态,防止在Widget销毁后调用导航或状态更新导致报错
内容的提问来源于stack exchange,提问作者user9239214
相关产品推荐
相关产品推荐

