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

Flutter应用集成AdMob广告后无网络环境下初始化崩溃问题求助

解决Flutter AdMob无网络环境下初始化崩溃问题

你遇到的问题核心是AdMob初始化与广告加载过程中未处理异步异常和无网络场景,导致无网络时未捕获的错误触发应用崩溃。下面一步步帮你排查和修复:

问题诊断

  1. 异步方法同步调用:MobileAds.instance.initialize()是异步方法,但你在main函数里直接同步调用,没有等待其完成,无网络时初始化抛出的异常无法被捕获。
  2. 强制解包风险:_bannerAd!.load()使用了强制解包操作,若广告对象创建过程中出现异常导致_bannerAd为null,会直接触发空指针崩溃。
  3. 无异常捕获机制:初始化和广告加载全程没有异常捕获逻辑,无网络时的加载失败会直接扩散为应用级崩溃。

修复方案

1. 修正Main函数的异步初始化逻辑

将AdMob的初始化改为异步等待,并添加异常捕获,确保无网络时初始化失败不会导致应用崩溃:

void main() async { 
  WidgetsFlutterBinding.ensureInitialized(); 

  // 异步初始化AdMob并捕获异常
  try {
    await MobileAds.instance.initialize();
    print("AdMob初始化成功");
  } catch (e) {
    print("AdMob初始化失败(大概率无网络): $e");
    // 无网络时可在此做降级处理,比如标记不加载广告
  }

  SystemChrome.setPreferredOrientations( 
    [DeviceOrientation.portraitUp, DeviceOrientation.portraitDown]); 
  runApp(const MyApp()); 
}

2. 重构AdMobService类,添加异常处理与安全调用

修改AdMobService的初始化和广告加载逻辑,去掉无效的null判断,添加异常捕获,避免强制解包:

class AdMobService { 
  InterstitialAd? _interstitialAd; 
  BannerAd? _bannerAd; 

  static String get bannerAdUnitId => Platform.isAndroid 
      ? "ca-app-pub-3940256099942544/6300978111" 
      : "ca-app-pub-3940256099942544/6300978111"; 

  // 改为异步初始化方法(作为main初始化的备用逻辑)
  static Future<void> initialize() async { 
    try {
      await MobileAds.instance.initialize();
    } catch (e) {
      print("AdMob服务初始化异常: $e");
    }
  } 

  bool createBannerAd() { 
    // 先释放已存在的广告,避免内存泄漏
    if (_bannerAd != null) {
      _bannerAd!.dispose();
      _bannerAd = null;
    }

    _bannerAd = BannerAd( 
      adUnitId: bannerAdUnitId, 
      size: AdSize.smartBanner, 
      request: AdRequest(), 
      listener: BannerAdListener( 
        onAdLoaded: (Ad ad) => print("Banner广告加载完成"), 
        onAdFailedToLoad: (Ad ad, LoadAdError error) { 
          print("Banner广告加载失败: ${error.message}");
          ad.dispose(); 
          _bannerAd = null; 
        }, 
        onAdOpened: (Ad ad) => print("Banner广告打开"), 
        onAdClosed: (Ad ad) => print("Banner广告关闭")
      ), 
    ); 

    if (_bannerAd == null) { 
      return false; 
    } 

    // 加载广告时添加异常捕获
    try {
      _bannerAd!.load();
      return true;
    } catch (e) {
      print("加载Banner广告时发生异常: $e");
      _bannerAd?.dispose();
      _bannerAd = null;
      return false;
    }
  } 

  BannerAd? showBannerAd() { 
    return _bannerAd; 
  } 
}

3. 可选:添加网络状态判断(提前避免无网络加载)

你可以引入connectivity_plus包监听网络状态,在无网络时直接跳过广告加载,减少不必要的错误:

// 先在pubspec.yaml添加依赖:connectivity_plus: ^4.0.1
import 'package:connectivity_plus/connectivity_plus.dart';

// 修改createBannerAd为异步方法,先检查网络
Future<bool> createBannerAd() async { 
  var connectivityResult = await Connectivity().checkConnectivity();
  if (connectivityResult == ConnectivityResult.none) {
    print("当前无网络,跳过广告加载");
    return false;
  }

  // 后续的广告创建和加载逻辑...
}

4. 广告加载时机优化

建议在StatefulWidget的initState方法中调用createBannerAd,而非应用启动时直接加载,让应用有足够时间完成初始化,降低崩溃概率:

class HomePage extends StatefulWidget {
  const HomePage({super.key});

  @override
  State<HomePage> createState() => _HomePageState();
}

class _HomePageState extends State<HomePage> {
  @override
  void initState() {
    super.initState();
    // 延迟一点再加载广告,避免和应用初始化抢资源
    Future.delayed(const Duration(seconds: 1), () {
      AdMobService().createBannerAd();
    });
  }

  // ...
}

关键注意点

  • 永远不要同步调用异步方法,一定要用await等待并捕获异常
  • 避免使用!强制解包可空对象,尽可能用null安全的方式处理
  • 广告对象使用完毕后一定要调用dispose(),避免内存泄漏

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.29 18:27:40