前言

最近在 Windows 环境下重新运行 Flutter 项目 Memoria 智能影记,项目主要功能是对手机相册进行扫描,并结合本地 AI、ML Kit、TFLite、云端 LLM 等模块完成图片/视频语义分析。

运行命令如下:

flutter run --dart-define-from-file=config/profiles/dev.json

结果从依赖下载、Flutter SDK 版本、Gradle 构建,到 Android 真机运行日志,连续遇到了一系列问题。本文记录完整排查过程,方便之后复现和快速定位。


一、环境信息

项目运行命令:

flutter run --dart-define-from-file=config/profiles/dev.json

二、问题一:flutter pub get 报 TLS error

最开始运行时出现:

Got TLS error trying to find package llamadart at https://pub.flutter-io.cn.
Failed to update packages.

当时 Flutter 提示:

Flutter assets will be downloaded from https://storage.flutter-io.cn.

说明当前环境使用了 Flutter 中国镜像。问题点在于:

https://pub.flutter-io.cn

在拉取 Dart package 时出现 TLS 错误。

解决方法

切换 pub 镜像源。这里我使用的是上海交大镜像:

$env:PUB_HOSTED_URL="https://mirror.sjtu.edu.cn/dart-pub"
$env:FLUTTER_STORAGE_BASE_URL="https://mirror.sjtu.edu.cn"

然后重新执行:

flutter pub get

依赖成功下载:

Got dependencies.
Changed 5 dependencies!

说明此时 pub 依赖问题已经解决。


三、问题二:Flutter API 不兼容,找不到 ScrollCacheExtent

依赖下载成功后,再次运行:

flutter run --dart-define-from-file=config/profiles/dev.json

出现编译错误:

Error: Couldn't find constructor 'ScrollCacheExtent.pixels'.
Error: No named parameter with the name 'scrollCacheExtent'.

对应代码位置:

lib/view/pages/album_page.dart:1522
lib/view/pages/album_search_page.dart:997
lib/view/pages/create_page.dart:676

代码里使用了:

scrollCacheExtent: const ScrollCacheExtent.pixels(700),

这个 API 在当前 Flutter 3.41.3 中不可用,因此编译失败。

解决方案 1:升级 Flutter

查看 Flutter 版本:

flutter --version

输出:

Flutter 3.41.3
Dart 3.11.1

切换 stable 并升级:

flutter channel stable
flutter upgrade

第一次升级时因为 Dart SDK 下载失败,报错:

Invoke-WebRequest : 基础连接已经关闭: 发送时发生错误
Error: Unable to update Dart SDK after 3 retries.

继续使用上海交大镜像:

$env:PUB_HOSTED_URL="https://mirror.sjtu.edu.cn/dart-pub"
$env:FLUTTER_STORAGE_BASE_URL="https://mirror.sjtu.edu.cn"
flutter upgrade

升级成功:

Flutter 3.44.2 • channel stable
Dart 3.12.2

解决方案 2:改回旧 API

如果不想升级 Flutter,也可以把:

scrollCacheExtent: const ScrollCacheExtent.pixels(700),

改成兼容旧版本的写法:

cacheExtent: 700.0,

这两个参数的核心目的都是让滚动视图提前缓存可视区域外的一部分内容,减少快速滚动时的卡顿。

可以用 PowerShell 一键替换:

$files = @(
  "lib/view/pages/album_page.dart",
  "lib/view/pages/album_search_page.dart",
  "lib/view/pages/create_page.dart"
)

foreach ($f in $files) {
  (Get-Content $f -Raw) `
    -replace "scrollCacheExtent:\s*const ScrollCacheExtent\.pixels\(700\),", "cacheExtent: 700.0," |
    Set-Content $f
}

检查是否替换干净:

rg "scrollCacheExtent|ScrollCacheExtent" lib

如果没有输出,说明已经替换完成。


四、问题三:Gradle 找不到 flutter_embedding_debug

升级 Flutter 后,再次运行项目,出现新的 Gradle 错误:

Could not find io.flutter:flutter_embedding_debug:1.0.0-77e2e94772b6eb43759e34ed1ad7da4674e19cab.
Required by:
    project :amplify_db_common

这不是 amplify_db_common 插件本身损坏,而是 Android 构建时需要 Flutter engine 的 Maven artifact,但是 Gradle 没有成功拉到:

flutter_embedding_debug

解决方法

重新设置镜像,并清理 Flutter / Gradle 缓存:

$env:PUB_HOSTED_URL="https://mirror.sjtu.edu.cn/dart-pub"
$env:FLUTTER_STORAGE_BASE_URL="https://storage.flutter-io.cn"

cd D:\StudioProjects\Memoria

cd android
.\gradlew --stop
cd ..

flutter clean
flutter precache --android --force
flutter pub get
flutter run --dart-define-from-file=config/profiles/dev.json

这里关键是:

flutter precache --android --force

它会重新下载 Android 构建所需的 Flutter engine artifacts。


五、Kotlin Gradle Plugin 警告

运行时还出现了如下警告:

WARNING: Your Android app project applies the Kotlin Gradle Plugin,
which will cause build failures in future versions of Flutter.

以及:

Your app uses the following plugins that apply Kotlin Gradle Plugin:
amplify_analytics_pinpoint, amplify_auth_cognito, amplify_db_common, ...

这不是当前构建失败的直接原因,而是 Flutter 新版本对 Kotlin Gradle Plugin 的未来兼容性提醒。

当前可以先忽略,后续需要根据 Flutter 官方文档迁移到 Built-in Kotlin。


六、项目终于跑起来后的 Android 日志分析

成功运行后,控制台开始输出大量日志,例如:

I/flutter: [pipeline-progress] stage=UnifiedAnalysisStage.processing scan=430/4469 ai=234/440 msg=消费者已完成 234/440,失败 0

这说明项目已经正常启动,并且正在处理相册:

scan=430/4469:已经扫描 430 张,总共 4469 张
ai=234/440:AI 已完成 234 个任务,总任务约 440 个
失败 0:当前没有失败任务

也就是说,主流程已经跑通了。


七、运行日志中的几个常见 warning

1. SELinux 权限拒绝

日志中频繁出现:

W/binder: avc: denied { ioctl } for path="/proc/fas/render"

这是 vivo / Android 系统层面的 SELinux 日志。普通 app 没有权限访问 /proc/fas/render 这类系统节点,所以会被拒绝。

只要 app 没有 crash,一般可以忽略。


2. HWUI 图像解码日志

日志中还有:

W/HWUI: Image decoding logging dropped!

这表示 Android 图像解码相关日志太多,系统丢弃了一部分日志,不是致命错误。

还有:

D/HWUI: --- Failed to create image decoder with message 'unimplemented'

这通常表示某些图片或视频缩略图编码格式系统解码器不支持,例如:

HEIC
特殊视频帧
损坏图片
云端占位图
厂商私有格式缩略图

如果 pipeline 没有失败,可以暂时忽略。若后续发现某些图片缩略图无法显示,再针对性处理。


3. TFLite 日志

I/tflite: Replacing 65 out of 65 node(s) with delegate (TfLiteXNNPackDelegate)

这是正常日志,说明 TFLite 成功使用 XNNPack delegate 加速。


4. ML Kit / FaceDetector 日志

V/FaceDetectorV2Jni: detectFacesImageByteBuffer.start()
V/FaceDetectorV2Jni: detectFacesImageByteBuffer.end()

说明 ML Kit 人脸检测正在正常工作。


5. GC 日志

NativeAlloc concurrent copying GC freed ...
LOS objects ...

说明项目在进行大量图片解码、本地 AI 推理、缩略图处理时,产生了较多大对象,触发了 GC。

首次扫描几千张照片时,这是正常现象。但如果后续出现明显卡顿或 OOM,需要优化图片解码尺寸、任务队列和缓存策略。


八、当前真正需要优化的点

虽然项目已经跑起来,但从日志看还有几个工程优化点。

1. 不要在日志里打印 token

当前日志中出现:

[AuthInterceptor] https://xxx/chat/completions token=eyJraWQiOi...

这是非常危险的。即使只打印 token 前缀,也不建议出现在控制台日志里。

建议改成:

debugPrint('[AuthInterceptor] ${options.uri} auth=true');

或者:

debugPrint('[AuthInterceptor] ${options.uri} token=<redacted>');

不要打印真实 token:

debugPrint('token=$token');

尤其是隐私相册类 app,日志中暴露 token 是非常严重的安全隐患。


2. 进度日志需要节流

当前几乎每处理一张图都会打印日志:

[pipeline-progress] ...
[progress-receive] ...

如果相册有几千张图片,日志会非常多,影响调试体验,也可能影响性能。

可以改成每 10 张或每 20 张打印一次:

if (scanCount % 10 == 0) {
  debugPrint('[pipeline-progress] scan=$scanCount/$total ai=$aiDone/$aiTotal');
}

3. AI 队列需要背压

日志中出现:

[pipeline] 已按 10 张一组移交前台服务串行 AI,total=440 queue=207

说明生产者扫描很快,但消费者 AI 处理较慢,队列积压到了 200 多。

建议给队列设置上限,例如:

while (queue.length > 200) {
  await Future.delayed(const Duration(milliseconds: 500));
}

这样可以避免首次扫描时:

内存压力过大
网络请求过多
手机发热
UI 卡顿
GC 频繁

九、最终解决流程总结

本次完整修复流程如下:

# 1. 设置镜像
$env:PUB_HOSTED_URL="https://mirror.sjtu.edu.cn/dart-pub"
$env:FLUTTER_STORAGE_BASE_URL="https://mirror.sjtu.edu.cn"

# 2. 升级 Flutter
flutter channel stable
flutter upgrade

# 3. 检查环境
flutter doctor -v

# 4. 若 Android embedding 缺失,重新 precache
$env:FLUTTER_STORAGE_BASE_URL="https://storage.flutter-io.cn"
flutter clean
flutter precache --android --force
flutter pub get

# 5. 运行项目
flutter run --dart-define-from-file=config/profiles/dev.json

最终项目成功运行,并进入相册扫描和 AI 分析流程:

scan=430/4469
ai=234/440
失败 0

十、总结

这次问题表面上看是 Flutter 项目运行失败,但实际包含了多个层次:

1. pub 镜像 TLS 问题
2. Flutter SDK API 版本不匹配
3. Flutter upgrade 下载 Dart SDK 失败
4. Gradle 找不到 flutter_embedding_debug
5. Android 真机运行时系统 warning 较多
6. 首次相册扫描导致大量 AI / 图像解码 / GC 日志

最终结论:

pub TLS 错误:换镜像
ScrollCacheExtent 报错:升级 Flutter 或改成 cacheExtent
flutter_embedding_debug 缺失:flutter precache --android --force
运行时大量 warning:大部分不是致命错误
真正需要优化:token 日志、进度日志节流、AI 队列背压

对于 Flutter + Android + AI 相册类项目来说,首次运行时遇到大量系统日志是正常现象。判断是否真正出问题,关键不要只看 W/D/ 日志,而要重点关注:

FATAL EXCEPTION
OutOfMemoryError
DioException
SocketException
PlatformException
失败数是否增加
pipeline 是否停止推进

只要主流程持续推进,且失败数为 0,就说明项目核心链路已经跑通。

更多推荐