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

Flutter集成AdMob后fluttertoast报MissingPluginException的解决方法

解决Flutter Toast在集成AdMob后报MissingPluginException的问题

首先得明确:这个问题不是AdMob和fluttertoast的冲突,真正的根源是你把Fluttertoast.showToast()放在了AndroidAlarmManager的回调callback函数里——而这个回调是运行在独立的后台Isolate中的,Flutter的平台插件(包括fluttertoast)只能在主Isolate中正常工作,因为平台通道的初始化是绑定在主Isolate上的,后台Isolate无法直接访问这些插件实现。

解决方案:通过Isolate间通信让主Isolate显示Toast

我们可以利用IsolateNameServer在后台Isolate和主Isolate之间建立通信,让主Isolate来执行显示Toast的操作(只有主Isolate能正常调用平台插件)。

步骤1:在主Isolate中注册消息监听端口

修改你的_AlertTime2State类,添加端口注册和监听逻辑:

class _AlertTime2State extends State<AlertTime2> {
  // 用于接收后台Isolate消息的端口
  ReceivePort _toastPort = ReceivePort();
  
  @override
  void initState() {
    super.initState();
    // 注册端口,让后台Isolate可以通过名称找到它
    IsolateNameServer.registerPortWithName(
        _toastPort.sendPort, 'toast_message_port');
    
    // 监听来自后台Isolate的消息,收到后显示Toast
    _toastPort.listen((message) {
      if (message is String) {
        Fluttertoast.showToast(
          msg: message,
          toastLength: Toast.LENGTH_LONG,
          gravity: ToastGravity.BOTTOM,
          backgroundColor: Colors.black,
          textColor: Colors.red,
          fontSize: 16.0,
        );
      }
    });

    // 你的原有初始化代码:FirebaseAdMob、BannerAd等
    FirebaseAdMob.instance.initialize(
        appId: "xxxxxxxxxxxxxxxxxxxxxx");
    _bannerAd = createBannerAd()
      ..load()
      ..show();
    initPlatformState();
    FileUtils().readFromFile().then((String value) {
      setState(() {
        _selectedTime = value;
      });
    });
  }

  @override
  void dispose() {
    // 销毁时移除端口注册,避免内存泄漏
    IsolateNameServer.removePortNameMapping('toast_message_port');
    _toastPort.close();
    
    // 你的原有销毁代码
    _bannerAd?.dispose();
    _interstitialAd?.dispose();
    super.dispose();
  }

  // 其他原有代码...
}

步骤2:修改后台Isolate的回调函数

让callback不再直接调用Fluttertoast,而是通过注册的端口给主Isolate发送消息:

Future<void> callback() async {
  print("I am in the isolate");
  
  // 查找主Isolate注册的端口
  SendPort sendPort = IsolateNameServer.lookupPortByName('toast_message_port');
  if (sendPort != null) {
    // 发送要显示的Toast内容给主Isolate
    sendPort.send("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
  }
  
  print("last line of Isolate");
}

补充说明

  • 为什么集成AdMob后才出现问题?可能是之前你的AlarmManager回调没有被正确触发,或者AdMob的初始化改变了插件的加载顺序,导致后台Isolate完全无法访问插件通道,但核心原因始终是后台Isolate不能直接调用Flutter平台插件。
  • 所有需要访问平台通道(比如Toast、传感器、原生API)或者UI操作的代码,都必须放在主Isolate中执行,后台Isolate只能做纯计算类的任务,然后通过消息通知主Isolate处理相关操作。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.07 21:07:33