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

如何解决调用google_mlkit_text_recognition时反复出现NativeAlloc GC日志问题

Google ML Kit文字识别导致GC日志反复输出的解决方法

问题场景与代码实现

我使用google_mlkit_text_recognition包实现图片文字识别,在ViewModel中编写了recognizingText方法:

bool _isPrespection = false;
bool get isPrespect => _isPrespection;
Future<void> recognizingText(XFile? images) async {
  final inputImage = InputImage.fromFilePath(images!.path);
  final textRecognizer = TextRecognizer();
  final recognizedText = await textRecognizer.processImage(inputImage);
  textRecognizer.close();

  var resulttext = '';
  for (TextBlock block in recognizedText.blocks) {
    for (TextLine line in block.lines) {
      resulttext = "$resulttext  ${line.text}";
    }
  }
  print(resulttext);
}

在无状态Widget中通过Provider调用该方法:

var uploadImageModel =
    Provider.of<uploaPrespectionViewmodelProvider>(context);
uploadImageModel.recognizingText(images);

调用后控制台反复输出以下GC日志,直至应用停止运行:

NativeAlloc concurrent copying GC freed 42116(1410KB) AllocSpace objects, 12(296KB) LOS objects, 49% free, 4935KB/9871KB, paused 159us total 122.025ms

解决方法

  • 避免在Widget的build方法中重复调用识别逻辑
    如果当前是在build方法内直接调用recognizingText,每次Widget重建(比如状态变化、布局更新)都会触发文字识别,导致大量对象创建销毁,引发频繁GC。需将调用逻辑转移到一次性触发的回调中,比如图片选择完成后的回调、按钮点击事件等。

  • 复用TextRecognizer实例
    不要每次调用识别方法都创建新的TextRecognizer,将其作为ViewModel的成员变量初始化一次,销毁时统一关闭,减少对象频繁创建回收带来的GC压力。修改后的ViewModel示例:

    bool _isPrespection = false;
    bool get isPrespect => _isPrespection;
    TextRecognizer? _textRecognizer;
    
    // 若ViewModel继承自ChangeNotifier,在初始化时创建实例
    @override
    void initState() {
      super.initState();
      _textRecognizer = TextRecognizer();
    }
    
    Future<void> recognizingText(XFile? images) async {
      if (images == null || _textRecognizer == null) return;
      
      final inputImage = InputImage.fromFilePath(images.path);
      final recognizedText = await _textRecognizer!.processImage(inputImage);
    
      // 后续处理逻辑...
    }
    
    // 销毁时回收资源
    @override
    void dispose() {
      _textRecognizer?.close();
      super.dispose();
    }
    
  • 优化字符串拼接逻辑
    原代码中用resulttext = "$resulttext ${line.text}"拼接字符串,每次拼接都会生成新的字符串对象,大量操作会加重GC负担。改用StringBuffer优化:

    StringBuffer resultBuffer = StringBuffer();
    for (TextBlock block in recognizedText.blocks) {
      for (TextLine line in block.lines) {
        resultBuffer.write("  ${line.text}");
      }
    }
    String resulttext = resultBuffer.toString();
    print(resulttext);
    
  • 添加并发调用锁
    在ViewModel中添加状态标记,避免同一时间多次触发识别,防止重复执行带来的资源消耗:

    bool _isRecognizing = false;
    
    Future<void> recognizingText(XFile? images) async {
      if (images == null || _isRecognizing) return;
      _isRecognizing = true;
      try {
        // 原有识别与处理逻辑
      } finally {
        _isRecognizing = false;
      }
    }
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.10 07:58:25