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

Flutter加载屏优先显示,延后执行Java原生数据请求方案咨询

解决Flutter加载屏被Java原生网络请求阻塞的问题

看起来你遇到的核心问题是Java端的同步阻塞操作卡住了Flutter的UI初始化流程,导致加载屏没法及时渲染,直接出现白屏直到请求完成。咱们一步步来修复这个问题:

第一步:修复Java端的阻塞逻辑

你原来的getReal2()方法里用了while (!completableFuture.isDone()) {}轮询+completableFuture.get()同步等待,这会直接阻塞configureFlutterEngine所在的线程——而这个线程正是Flutter用来初始化UI的关键线程,自然会导致加载屏迟迟显示不出来。

咱们把Java代码改成异步回调的方式,让网络请求在后台线程执行,完成后再把结果返回给Flutter,完全不阻塞主线程:

public class MainActivity extends FlutterActivity { 
    private static final String CHANNEL = "samples.flutter.dev/battery"; 

    @Override 
    public void configureFlutterEngine(FlutterEngine flutterEngine) { 
        super.configureFlutterEngine(flutterEngine); 
        new MethodChannel(flutterEngine.getDartExecutor().getBinaryMessenger(), CHANNEL) 
            .setMethodCallHandler( (call, result) -> { 
                if (call.method.equals("getDate")) {
                    // 异步执行网络请求,不阻塞当前线程
                    CompletableFuture.supplyAsync(() -> {
                        try {
                            return getCoffee();
                        } catch (IOException e) {
                            e.printStackTrace();
                            return null;
                        }
                    }).whenComplete((coffeeList, throwable) -> {
                        if (throwable != null) {
                            // 请求出错时返回错误信息给Flutter
                            result.error("NETWORK_ERROR", "Failed to fetch coffee data", throwable.getMessage());
                        } else if (coffeeList == null) {
                            result.error("NO_DATA", "No coffee data retrieved", null);
                        } else {
                            // 请求成功,返回结果
                            result.success(coffeeList);
                        }
                    });
                } else { 
                    result.notImplemented(); 
                } 
            } ); 
    } 

    public static List<String> getCoffee() throws IOException { 
        ArrayList<String> coffee = new ArrayList<>(); 
        Document doc = Jsoup.connect("https://www.bankofabyssinia.com").timeout(6000).get(); 
        for(int i=0;i<=8;i++) { 
            for (int j=2;j<=3;j++){ 
                coffee.add(doc.select("#myTable > tbody > tr:nth-child("+i+") > td:nth-child("+j+")").text()); 
            } 
        } 
        return coffee; 
    } 
}

第二步:调整Flutter端的请求时机

原来你在initState里直接调用getWholeJava(),这时候Widget还没完成第一帧渲染,可能导致加载屏还没来得及显示就进入请求等待。咱们改成等加载屏渲染完成后再发起请求:

import 'dart:io'; 
import 'package:flutter/material.dart'; 
import 'package:flutter/services.dart'; 
import 'Home.dart'; 

class Load extends StatefulWidget { 
    @override 
    _LoadState createState() => _LoadState(); 
} 

class _LoadState extends State<Load> { 
    static const platform = const MethodChannel('samples.flutter.dev/battery'); 

    void getWholeJava() async { 
        try { 
            final List result = await platform.invokeMethod('getDate'); 
            Navigator.of(context).pushReplacement(MaterialPageRoute( 
                builder: (BuildContext context) => Home( whole: result, ))); 
        } on PlatformException catch (e) { 
            print("Error fetching data: ${e.message}");
            // 这里可以添加错误提示,比如显示一个重试按钮
        } 
    } 

    @override 
    void initState() { 
        super.initState(); 
        // 等待当前帧渲染完成后再发起请求,确保加载屏先显示出来
        WidgetsBinding.instance.addPostFrameCallback((_) {
            getWholeJava();
        });
    } 

    @override 
    Widget build(BuildContext context) { 
        return Scaffold(
            body: Container(
                child: Center(
                    child: Column(
                        mainAxisAlignment: MainAxisAlignment.center, // 居中显示加载文本
                        children: <Widget>[ 
                            Text( 
                                'The app is loading', 
                                style: TextStyle( 
                                    fontSize: 40.0, 
                                    fontWeight: FontWeight.w900, 
                                    color: Colors.green[900]), 
                            ), 
                            // 可以加个CircularProgressIndicator让加载状态更明显
                            SizedBox(height: 20),
                            CircularProgressIndicator(color: Colors.green[900]),
                        ] 
                    )
                ), 
            )
        ); 
    } 
}

为什么原来的代码不生效?

  1. Java端阻塞线程:你原来的while循环+get()会卡住FlutterEngine的初始化线程,导致Flutter根本没时间渲染加载屏,直接进入白屏等待。
  2. Flutter请求时机过早:initState在Widget初始化时就执行,这时候UI还没完成绘制,即使Java端不阻塞,加载屏也可能来不及显示。

额外优化建议

  • 添加错误处理UI:如果网络请求失败,不要只打印日志,给用户显示一个重试按钮或者错误提示。
  • 优化加载屏体验:比如添加动画、品牌logo,让用户感知到App正在正常工作。
  • 考虑用Flutter原生的网络请求库(比如http、dio)替代Java原生请求,这样可以减少跨平台通信的复杂度,也更容易在Flutter端控制请求时机和状态。

内容的提问来源于stack exchange,提问作者Marven

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.08 20:43:15