You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 07:00:14