如何解决调用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
相关产品推荐
相关产品推荐

