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

如何实现Flutter桌面应用单实例运行?Mutex方案失效求解决

Flutter桌面应用阻止多实例运行的正确实现方案

原代码使用的package:mutex的Mutex是进程内互斥锁,仅能限制同一进程内的并发操作,无法跨进程生效。不同应用实例属于独立进程,内存完全隔离,所以这个方案根本无法阻止多实例运行。

以下是两种可行的实现方案:

方案一:使用文件锁(无需额外依赖)

利用dart:io的文件独占锁特性,创建一个全局唯一的锁文件,当第二个实例尝试获取锁时会失败,以此判断是否已有实例在运行。注意锁需要持续持有直到应用退出,不能提前释放。

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

void main() async {
  // 定义全局唯一的锁文件路径,可根据系统调整
  final lockFile = File(Platform.isWindows 
      ? '${Platform.environment['APPDATA']}\\my_app.lock'
      : '${Platform.environment['HOME']}/.my_app.lock');

  FileLock? lock;
  try {
    // 尝试获取独占锁,阻塞直到拿到锁或失败
    lock = await lockFile.open(mode: FileMode.write).then((file) {
      return file.lockSync(FileLock.exclusive);
    });
    // 成功获取锁,运行应用
    runApp(const MyApp());
  } catch (_) {
    // 获取锁失败,说明已有实例在运行
    print('应用已在运行中');
    exit(0);
  }

  // 应用退出时释放锁(可选,进程结束后系统会自动释放)
  WidgetsBinding.instance.addObserver(LifecycleObserver(() {
    lock?.release();
    lockFile.deleteSync();
  }));
}

class LifecycleObserver extends WidgetsBindingObserver {
  final VoidCallback onExit;

  LifecycleObserver(this.onExit);

  @override
  void didChangeAppLifecycleState(AppLifecycleState state) {
    if (state == AppLifecycleState.detached) {
      onExit();
    }
  }
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(body: Center(child: Text('单实例应用'))),
    );
  }
}

方案二:使用single_instance包(更简洁)

这个包专门用于处理Flutter桌面应用的单实例问题,内部封装了跨平台的互斥逻辑。

  1. 添加依赖到pubspec.yaml:
dependencies:
  single_instance: ^2.0.0
  1. 实现代码:
import 'package:flutter/material.dart';
import 'package:single_instance/single_instance.dart';
import 'dart:io';

void main() async {
  // 创建唯一实例标识符,建议用应用的包名
  final instanceId = 'com.yourcompany.yourapp';
  
  // 尝试创建单实例
  final isFirstInstance = await SingleInstance.create(instanceId);
  
  if (isFirstInstance) {
    runApp(const MyApp());
  } else {
    print('应用已在运行中');
    exit(0);
  }
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(body: Center(child: Text('单实例应用'))),
    );
  }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.25 18:42:33