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
相关产品推荐
相关产品推荐

