IDE 层面:Android Studio 基于 IntelliJ IDEA 扩展而来,复用了 IntelliJ IDEA 强大的代码编辑器和开发者工具等 IDE 基础能力,在此之上 Android Studio 提供了更多提高 Android 构建效率的功能,如 Android 模拟器、代码模版等等。另外 Android Studio 也将自身专业的 Android 应用开发能力反哺给 IntelliJ IDEA,以 Android IDEA Plugin 的形式,使 IntelliJ IDEA 支持 Android 应用开发,二者互相赋能,相辅相成。Gradle 层面:Gradle 是一个灵活而强大的开源构建系统,它除了提供跨平台的可执行程序支持命令行执行 Gradle 构建外,还专门提供了 Gradle Tooling API 编程 SDK,供外部更方便、更紧密的将 Gradle 构建能力嵌入到 IDE 中,IntelliJ IDEA、Eclipse、VSCode 等 IDE 都采用了这种方式。在 Gradle 源码中也有专门服务于 IntelliJ IDEA、Eclipse 等 IDE 的代码模块,构建工具和 IDE 两个角色之间同样是互相赋能,强强联合。Plugin 层面:Plugin 层面包括 Android IDEA Plugin 和 Android Gradle Plugin,Android IDEA Plugin 为 IntelliJ IDEA/Android Studio 拓展了 Android 应用开发能力;Android Gradle Plugin 为 Gradle 拓展了 Android 应用构建能力。谷歌通过这两个 Plugin 将现代成熟优秀的 IDE 开发能力和构建工具联合在一起为 Android 所用,相比于早期 Eclipse 加 ANT 构建的开发方式,大幅提升了 Android 应用开发效率和体验。
调用过程中涉及到的关键类:GradleSyncInvoker:触发 Sync 的入口类,在 Android Studio 多处需要执行 Sync 的地方,都是通过调用此类的 requestProjectSync 方法来触发的ExternalSystemUtil:GradleSyncInvoker、GradleSyncExecutor 等类是专门针对 Sync 功能的封装,Sync 是 Android Studio 中独有的操作,在 IntelliJ IDEA 中并没有 Sync 的概念,IntelliJ IDEA 通过 [Reload All Gradle Projects] 操作来触发解析工程的 Gradle 构建信息,直接从 ExternalSystemUtil 类开始执行GradleProjectResolver:负责具体执行 Sync,其中 resolveProjectInfo 方法是具体执行 Sync 逻辑的地方,该方法的定义如下:public DataNode<ProjectData> resolveProjectInfo(
@NotNull ExternalSystemTaskId id,
@NotNull String projectPath,
boolean isPreviewMode,
@Nullable S settings,
@NotNull ExternalSystemTaskNotificationListener listener)
throws ExternalSystemException, IllegalArgumentException, IllegalStateException
进入 GradleProjectResolver 的 resolveProjectInfo 方法中后,首先会对预览模式进行处理,如下代码所示,如果是预览模式,则会简单构造出对应的工程数据结构后立马返回,不进行任何的解析行为:if (isPreviewMode) {
String projectName = new File(projectPath).getName();
ProjectData projectData = new ProjectData(GradleConstants.SYSTEM_ID, projectName, projectPath, projectPath);
DataNode<ProjectData> projectDataNode = new DataNode<>(ProjectKeys.PROJECT, projectData, null);
......
return projectDataNode;
}if (projectPathFile.isFile() && projectPath.endsWith(GradleConstants.EXTENSION) && projectPathFile.getParent() != null) {
projectDir = projectPathFile.getParent();
if (settings != null) {
List<String> arguments = settings.getArguments();
if (!arguments.contains("-b") && !arguments.contains("--build-file")) {
settings.withArguments("-b", projectPath);
}
}
} else {
projectDir = projectPath;
}ModelBuilder<BuildEnvironment> modelBuilder = connection.model(BuildEnvironment.class);public interface BuildAction<T> extends Serializable {
T execute(BuildController controller);
}private static void configureExecutionArgumentsAndVmOptions(@NotNull GradleExecutionSettings executionSettings,
@NotNull DefaultProjectResolverContext resolverCtx,
boolean isBuildSrcProject) {
executionSettings.withArgument("-Didea.sync.active=true");
if (resolverCtx.isResolveModulePerSourceSet()) {
executionSettings.withArgument("-Didea.resolveSourceSetDependencies=true");
}
if (!isBuildSrcProject) {
for (GradleBuildParticipant buildParticipant : executionSettings.getExecutionWorkspace().getBuildParticipants()) {
executionSettings.withArguments(GradleConstants.INCLUDE_BUILD_CMD_OPTION, buildParticipant.getProjectPath());
}
}
GradleImportCustomizer importCustomizer = GradleImportCustomizer.get();
GradleProjectResolverUtil.createProjectResolvers(resolverCtx).forEachOrdered(extension -> {
if (importCustomizer == null || importCustomizer.useExtraJvmArgs()) {
ParametersList parametersList = new ParametersList();
for (Pair<String, String> jvmArg : extension.getExtraJvmArgs()) {
parametersList.addProperty(jvmArg.first, jvmArg.second);
}
executionSettings.withVmOptions(parametersList.getParameters());
}
executionSettings.withArguments(extension.getExtraCommandLineArgs());
});
}<extensionPoint
qualifiedName="org.jetbrains.plugins.gradle.projectResolve"
interface="org.jetbrains.plugins.gradle.service.project.GradleProjectResolverExtension"/><extensions defaultExtensionNs="org.jetbrains.plugins.gradle">
<projectResolve implementation=
"com.android.tools.idea.gradle.project.sync.idea.AndroidGradleProjectResolver"
order="first"/>
......
</extensions>List<String> jvmArgs = settings.getJvmArguments();
BuildEnvironment buildEnvironment = getBuildEnvironment(connection, id, listener, (CancellationToken)null, settings);
if (!jvmArgs.isEmpty()) {
Collection<String> merged;
if (buildEnvironment != null) {
BuildIdentifier buildIdentifier = getBuildIdentifier(buildEnvironment);
List<String> buildJvmArguments = buildIdentifier == null || "buildSrc".equals(buildIdentifier.getRootDir().getName())
? ContainerUtil.emptyList()
: buildEnvironment.getJava().getJvmArguments();
merged = mergeBuildJvmArguments(buildJvmArguments, jvmArgs);
} else {
merged = jvmArgs;
}
List<String> filteredArgs = ContainerUtil.mapNotNull(merged, s -> StringUtil.isEmpty(s) ? null : s);
operation.setJvmArguments(ArrayUtilRt.toStringArray(filteredArgs));
}...
List<String> filteredArgs = new ArrayList<>();
if (!settings.getArguments().isEmpty()) {
String loggableArgs = StringUtil.join(obfuscatePasswordParameters(settings.getArguments()), " ");
LOG.info("Passing command-line args to Gradle Tooling API: " + loggableArgs);
filteredArgs.addAll(ContainerUtil.mapNotNull(settings.getArguments(), s -> StringUtil.isEmpty(s) ? null : s));
...
}
filteredArgs.add("-Didea.active=true");
filteredArgs.add("-Didea.version=" + getIdeaVersion());
operation.withArguments(ArrayUtilRt.toStringArray(filteredArgs));| 来源 | 参数 |
| Android Studio 源码 | --init-script /private/var/folders/_4/j3fdr4nd0x7cf17yvt20f5c00000gp/T/ijmapper.gradle -Didea.sync.active=true -Didea.resolveSourceSetDependencies=true -Porg.gradle.kotlin.dsl.provider.cid=676307056703202 -Pkotlin.mpp.enableIntransitiveMetadataConfiguration=true --init-script/private/var/folders/_4/j3fdr4nd0x7cf17yvt20f5c00000gp/T/ijinit3.gradle -Didea.active=true -Didea.version=2021.3 |
| Android IDEA Plugin 扩展:com.android.tools.idea.gradle.project.sync.idea.AndroidGradleProjectResolver | --init-script /private/var/folders/_4/j3fdr4nd0x7cf17yvt20f5c00000gp/T/sync.studio.tooling4770.gradle -Djava.awt.headless=true --stacktrace-Pandroid.injected.build.model.only=true -Pandroid.injected.build.model.only.advanced=true -Pandroid.injected.invoked.from.ide=true -Pandroid.injected.build.model.only.versioned=3 -Pandroid.injected.studio.version=10.4.2 -Pandroid.injected.build.model.disable.src.download=true -Pidea.gradle.do.not.build.tasks=true |
| Kotlin IDEA Plugin 扩展:org.jetbrains.kotlin.idea.gradleJava.scripting.importing.KotlinDslScriptModelResolver | -Dorg.gradle.kotlin.dsl.provider.mode=classpath |
| Kotlin IDEA Plugin 扩展:org.jetbrains.kotlin.idea.gradleJava.scripting.importing.KotlinDslScriptModelResolver | -Porg.gradle.kotlin.dsl.provider.cid=676307056703202 |
| Kotlin IDEA Plugin 扩展:org.jetbrains.kotlin.idea.gradleJava.configuration.KotlinMPPGradleProjectResolver | -Pkotlin.mpp.enableIntransitiveMetadataConfiguration=true |
initscript {
dependencies {
classpath files([mapPath('/Users/bytedance/IDE/intellij-community/out/production/intellij.android.gradle-tooling'), mapPath('/Users/bytedance/IDE/intellij-community/out/production/intellij.android.gradle-tooling.impl'), mapPath('/Users/bytedance/.m2/repository/org/jetbrains/kotlin/kotlin-stdlib/1.5.10-release-945/kotlin-stdlib-1.5.10-release-945.jar')])
}
}
allprojects {
apply plugin: com.android.ide.gradle.model.builder.AndroidStudioToolingPlugin
}class AdditionalClassifierArtifactsModelBuilder : ParameterizedToolingModelBuilder<AdditionalClassifierArtifactsModelParameter> {
...GeneralCommandLine commandLine = new GeneralCommandLine();
commandLine.withEnvironment(settings.getEnv());
commandLine.withParentEnvironmentType(
settings.isPassParentEnvs() ? GeneralCommandLine.ParentEnvironmentType.CONSOLE : GeneralCommandLine.ParentEnvironmentType.NONE);
Map<String, String> effectiveEnvironment = commandLine.getEffectiveEnvironment();
operation.setEnvironmentVariables(effectiveEnvironment);public AllModels execute(final BuildController controller) {
...
fetchProjectBuildModels(wrappedController, isProjectsLoadedAction, myGradleBuild);
addBuildModels(wrappedController, myAllModels, myGradleBuild, isProjectsLoadedAction);
...
}private List<Runnable> getProjectModels(@NotNull BuildController controller,
@NotNull final AllModels allModels,
@NotNull final BasicGradleProject project,
boolean isProjectsLoadedAction) {
...
Set<ProjectImportModelProvider> modelProviders = getModelProviders(isProjectsLoadedAction);
for (ProjectImportModelProvider extension : modelProviders) {
extension.populateProjectModels(controller, project, modelConsumer);
}
...
}private void addBuildModels(@NotNull final ToolingSerializerAdapter serializerAdapter,
@NotNull BuildController controller,
@NotNull final AllModels allModels,
@NotNull final GradleBuild buildModel,
boolean isProjectsLoadedAction) {
Set<ProjectImportModelProvider> modelProviders = getModelProviders(isProjectsLoadedAction);
for (ProjectImportModelProvider extension : modelProviders) {
extension.populateBuildModels(controller, buildModel, modelConsumer);
}
...
}for (GradleProjectResolverExtension resolverExtension = tracedResolverChain;
resolverExtension != null;
resolverExtension = resolverExtension.getNext()) {
...
ProjectImportModelProvider modelProvider = resolverExtension.getModelProvider();
if (modelProvider != null) {
projectImportAction.addProjectImportModelProvider(modelProvider);
}
ProjectImportModelProvider projectsLoadedModelProvider = resolverExtension.getProjectsLoadedModelProvider();
if (projectsLoadedModelProvider != null) {
projectImportAction.addProjectImportModelProvider(projectsLoadedModelProvider, true);
}
}override fun populateProjectModels(controller: BuildController,
projectModel: Model,
modelConsumer: ProjectImportModelProvider.ProjectModelConsumer) {
controller.findModel(projectModel, GradlePluginModel::class.java)
?.also { pluginModel -> modelConsumer.consume(pluginModel, GradlePluginModel::class.java) }
controller.findModel(projectModel, KaptGradleModel::class.java)
?.also { model -> modelConsumer.consume(model, KaptGradleModel::class.java) }
}override fun populateBuildModels(
controller: BuildController,
buildModel: GradleBuild,
consumer: ProjectImportModelProvider.BuildModelConsumer) {
populateAndroidModels(controller, buildModel, consumer)
populateProjectSyncIssues(controller, buildModel, consumer)
}val androidModules: MutableList<AndroidModule> = mutableListOf()
buildModel.projects.forEach { gradleProject ->
findParameterizedAndroidModel(controller, gradleProject, AndroidProject::class.java)?.also { androidProject ->
consumer.consumeProjectModel(gradleProject, androidProject, AndroidProject::class.java)
val nativeAndroidProject = findParameterizedAndroidModel(controller, gradleProject, NativeAndroidProject::class.java)?.also {
consumer.consumeProjectModel(gradleProject, it, NativeAndroidProject::class.java)
}
androidModules.add(AndroidModule(gradleProject, androidProject, nativeAndroidProject))
}
}if (syncActionOptions.isSingleVariantSyncEnabled) {
chooseSelectedVariants(controller, androidModules, syncActionOptions)
}
如上图,对于 Gradle 来说,Sync 流程中 Android Studio 会通过 Gradle Tooling API 从 Gradle 侧获取一系列所需的 Gradle Model,除 Gradle 自身外,Gradle Plugin 也可以提供自定义的 Gradle Model。另外 Sync 流程中 Gradle 会经历自身定义的生命周期,聚焦此视角梳理流程如下:
当通过 BuildAction 获取 Gradle Model 时会触发 Gradle 的构建行为,Gradle 构建会经历自身生命周期定义的 Initialization、Configuration 和 Execution 阶段。最近在学习CAN,记录一下,也供大家参考交流。推荐几个我觉得很好的CAN学习,本文也是在看了他们的好文之后做的笔记首先是瑞萨的CAN入门,真的通透;秀!靠这篇我竟然2天理解了CAN协议!实战STM32F4CAN!原文链接:https://blog.csdn.net/XiaoXiaoPengBo/article/details/116206252CAN详解(小白教程)原文链接:https://blog.csdn.net/xwwwj/article/details/105372234一篇易懂的CAN通讯协议指南1一篇易懂的CAN通讯协议指南1-知乎(zhihu.com)视频推荐CAN总线个人知识总
Transformers开始在视频识别领域的“猪突猛进”,各种改进和魔改层出不穷。由此作者将开启VideoTransformer系列的讲解,本篇主要介绍了FBAI团队的TimeSformer,这也是第一篇使用纯Transformer结构在视频识别上的文章。如果觉得有用,就请点赞、收藏、关注!paper:https://arxiv.org/abs/2102.05095code(offical):https://github.com/facebookresearch/TimeSformeraccept:ICML2021author:FacebookAI一、前言Transformers(VIT)在图
关闭。这个问题不符合StackOverflowguidelines.它目前不接受答案。我们不允许提问寻求书籍、工具、软件库等的推荐。您可以编辑问题,以便用事实和引用来回答。关闭3年前。Improvethisquestion我正处于学习Ruby的阶段,我想查看一些小型库的源代码以了解它们是如何构建的。我不知道什么是小型图书馆,但希望SO能推荐一些易于理解的图书馆来学习。因此,如果有人知道一两个非常小的库,这是新手Rubyists学习的好例子,请推荐!我想使用Manveru'sInnatelib,因为它试图保持在2000LOC以下,但我还不熟悉其中经常使用的Ruby速记。也许大约100-5
由于匿名block和散列block看起来大致相同。我正在玩它。我做了一些严肃的观察,如下所示:{}.class#=>Hash好的,这很酷。空block被视为Hash。print{}.class#=>NilClassputs{}.class#=>NilClass为什么上面的代码和NilClass一样,下面的代码又显示了Hash?puts({}.class)#Hash#=>nilprint({}.class)#Hash=>nil谁能帮我理解上面发生了什么?我完全不同意@Lindydancer的观点你如何解释下面几行:print{}.class#NilClassprint[].class#A
我很难理解Ruby中sender和receiver的实际含义。它们一般是什么意思?到目前为止,我只是将它们理解为方法调用和获取其返回值的调用。但是,我知道我的理解还远远不够。谁能给我一个Ruby中发送者和接收者的具体解释? 最佳答案 面向对象中的一个核心概念是消息传递和早期概念化,这在很大程度上借鉴了计算的Actor模型。艾伦·凯(AlanKay)创造了面向对象一词并发明了最早的OO语言之一SmallTalk,他拥有voicedregretatusingatermwhichputthefocusonobjectsinsteadofo
rails新手。只是想了解\assests目录中的这两个文件。例如,application.js文件有如下行://=requirejquery//=requirejquery_ujs//=require_tree.我理解require_tree。只是将所有JS文件添加到当前目录中。根据上下文,我可以看出requirejquery添加了jQuery库。但是它从哪里得到这些jQuery库呢?我没有在我的Assets文件夹中看到任何jquery.js文件——或者直接在我的整个应用程序中没有看到任何jquery.js文件?同样,我正在按照一些说明安装TwitterBootstrap(http:
我在某些代码中遇到了三元组,但我无法理解条件:str.split(/',\s*'/).mapdo|match|match[0]==?,?match:"somestring"end.join我确实理解我是在某些点上拆分字符串并将总结果转换为数组,然后依次处理数组的每个元素。除此之外,我不知道发生了什么。 最佳答案 一种(稍微)不那么令人困惑的写法是:str.split(/',\s*'/).mapdo|match|ifmatch[0]==?,matchelse"somestring"endend.join我认为多行三元语句很糟糕,尤其是
有没有人成功地将S3存储桶读取为子文件夹?文件夹1--子文件夹2----文件3----文件4--文件1--文件2文件夹2--子文件夹3--文件5--文件6我的任务是读取文件夹1。我希望看到子文件夹2、文件1和文件2,但看不到文件3或文件4。现在,因为我将存储桶键限制为prefix=>'folder1/',你仍然会得到file3和4,因为它们在技术上具有folder1前缀。似乎真正做到这一点的唯一方法是吸收folder1下的所有键,然后使用字符串搜索从结果数组中实际排除file3和file4。有没有人有过这方面的经验?我知道像Transmit和Cyberduck这样的FTP风格的S3
一、系统定级信息系统运营使用单位按照等级保护管理办法和定级指南,自主确定信息系统的安全保护等级。有上级主管部门的,应当经上级主管部门审批。跨省或全国统一联网运行的信息系统可以由其主管部门统一确定安全保护等级。定级需要根据信息系统的实际情况合理定级。二、系统备案第二级以上信息系统定级单位到所在地设区的市级以上公安机关办理备案手续。省级单位到省公安厅网安总队备案,各地市单位一般直接到市级网安支队备案,也有部分地市区县单位的定级备案资料是先交到区县公安网监大队的,具体根据各地市要求来。信息系统运营、使用单位或者其主管部门应当在信息系统安全保护等级确定后30日内,到公安机关办理备案手续。三、初次测评信
关于yolov5训练时参数workers和batch-size的理解yolov5训练命令workers和batch-size参数的理解两个参数的调优总结yolov5训练命令python.\train.py--datamy.yaml--workers8--batch-size32--epochs100yolov5的训练很简单,下载好仓库,装好依赖后,只需自定义一下data目录中的yaml文件就可以了。这里我使用自定义的my.yaml文件,里面就是定义数据集位置和训练种类数和名字。workers和batch-size参数的理解一般训练主要需要调整的参数是这两个:workers指数据装载时cpu所使