背景
做flutter安卓的同学想必大多遇到过以下问题:
`Gradle threw an error while downloading artifacts from the network. Retrying to download...`
flutter项目在编译安卓工程时,在弱网/无梯子的情况下,非常容易出现上面这个问题,此时电脑的.gradle缓存会全部删除(即使以前有正确下载下来的)。一个项目的gradle缓存往往以G计算,且多为国外仓库,重新下载依然是漫长的等待,相信很多小伙伴半天一天的时候就交待在这里了;
分析问题
首先如果能确定项目能正常运行(别的同学可以),那在国内出现这种情况多半是因为网络问题,没梯子或者网络比较慢,如果是梯子问题我们可以换一些国内源,这里不做过多描述;如果是网络比较慢,.gradle缓存的删除会使得项目同步更加缓慢,起到反作用,这种情况我们就需要处理一下flutter的错误处理逻辑了,好在这些逻辑在flutter sdk源码当中,我们修改起来就比较方便;
修正flutter编译错误处理
1.来到flutter sdk目录,定位到flutter tools文件,放入编辑器,这里使用vscode或xcode或文本编辑器都可以;
~/flutter/packages/flutter_tools/lib/src/android/gradle_errors.dart
2.找到networkErrorHandler实现,我们发现了逻辑中有删除Home/.gradle的逻辑,汗;(这里也可以把.gradle移动到别的目录)
final GradleHandledError networkErrorHandler = GradleHandledError(
test: _lineMatcher(const <String>[
'java.io.FileNotFoundException: https://downloads.gradle.org',
'java.io.IOException: Unable to tunnel through proxy',
'java.lang.RuntimeException: Timeout of',
'java.util.zip.ZipException: error in opening zip file',
'javax.net.ssl.SSLHandshakeException: Remote host closed connection during handshake',
'java.net.SocketException: Connection reset',
'java.io.FileNotFoundException',
"> Could not get resource 'http",
]),
handler: ({
required String line,
required FlutterProject project,
required bool usesAndroidX,
required bool multidexEnabled,
}) async {
globals.printError(
'${globals.logger.terminal.warningMark} Gradle threw an error while downloading artifacts from the network. '
'Retrying to download...'
);
//罪魁祸首在这里!!
try {
final String? homeDir = globals.platform.environment['HOME'];
if (homeDir != null) {
final Directory directory = globals.fs.directory(globals.fs.path.join(homeDir, '.gradle'));
ErrorHandlingFileSystem.deleteIfExists(directory, recursive: true);
}
} on FileSystemException catch (err) {
globals.printTrace('Failed to delete Gradle cache: $err');
}
return GradleBuildStatus.retry;
},
eventLabel: 'network',
);
3.果断注释try-catch内的下载逻辑;
4.编译Flutter工具脚本
注意此时跑项目还是会遇到上面的问题,因为fluttertools在运行的时候不是运行源码,而是运行二进制编译产物,我们在~/flutter/bin/cache里找到flutter_tools.snapshot、flutter_tools.stamp并删除;执行下面命令重新编译
#方式一:(推荐,flutter自动编译缺少的flutter_tools二进制文件)
flutter doctor
#方式二:(手动编译)
dart --snapshot=flutter_tools.snapshot ../../packages/flutter_tools/bin/flutter_tools.dart
至此又可以愉快的进行flutter开发了~
总结
本文主要讲解如何处理flutter项目在编译过程种,如果gradle同步失败会自动删除gradle缓存的问题,造成无限下载、无限删除、无限等待,如果项目本身就依赖了一些国内无法访问的maven源,同步过程中遇到域名都无法解析那种,就老老实实找梯子、找国内镜像吧;