androidgradle源码,Androidgradle打包涉及task源码解析
(五)
⽂章序号
此篇⽂章将分析如下3个task。
:app:transformClassesWithDexBuilderForDebug
:app:transformDexArchiveWithExternalLibsDexMergerForDebug
:app:transformDexArchiveWithDexMergerForDebug
transform vs task
本篇⽂章主要分析transform相关的任务,分析transform任务之前跟⼤家⼤致的聊下transform和task的关联。
在本篇之前的⽂章分析的task基本都是Task的⼦类。 transform相关的任务均是Transform的⼦类。那task和transform有什么关联呢?先看下Transform:
public abstract class Transform {
public abstract String getName();
public abstract Set getInputTypes();
public Set getOutputTypes() {
return getInputTypes();
}
public abstract Set super Scope> getScopes();
public Set super Scope> getReferencedScopes() {
return ImmutableSet.of();
}
public Collection getSecondaryFileInputs() {
return ImmutableList.of();
}
public Collection getSecondaryFiles() {
return ImmutableList.of();
}
public Collection getSecondaryFileOutputs() {
return ImmutableList.of();
}
public Collection getSecondaryDirectoryOutputs() {
return ImmutableList.of();
}
public Map getParameterInputs() {
return ImmutableMap.of();
}
public abstract boolean isIncremental();
public void transform(
@NonNull Context context,
@NonNull Collection inputs,
@NonNull Collection referencedInputs,
@Nullable TransformOutputProvider outputProvider,
boolean isIncremental) throws IOException, TransformException, InterruptedException {
}
public void transform(@NonNull TransformInvocation transformInvocation)
throws TransformException, InterruptedException, IOException {
// Just delegate to old method, for code that uses the old API.
//noinspection deprecation
Context(), Inputs(),
transformInvocation.isIncremental());
}
public boolean isCacheable() {
return false;
}
}
Transform实际就是⼀个抽象类,提供了⼀些抽象⽅法,仔细看会发现很多⽅法定义的和Task中的⽅法定义的很类似。接下来我们下TransformManager.java⾥⾯的addTransform()⽅法:
public Optional> addTransform(
@NonNull TaskFactory taskFactory,
@NonNull TransformVariantScope scope,
@NonNull T transform,
@Nullable TransformTask.ConfigActionCallback callback) {
...
transforms.add(transform);
// create
AndroidTask task =
taskFactory,
new TransformTask.ConfigAction<>(
transform和convert的区别
taskName,
transform,
inputStreams,
referencedStreams,
outputStream,
recorder,
callback));
return Optional.ofNullable(task);
}
addTransform ⽅法在执⾏过程中,会将 Transform 包装成⼀个 AndroidTask 对象,所以transfrom最终会被转换成⼀个task。了解了transform,我们接下来继续分析这⼏个task。
transformClassesWithDexBuilderForDebug
输⼊命令:./gradlew transformClassesWithDexBuilderForDebug
inputs&outputs
input file:/Users/chao.zheng/.gradle/caches/transforms-1/files-1.1/appcompat-v7-
26.1.0.aar/6b443e96f1af9aa241aaa70576c67a57/jars/classes.jar
input file:/Users/chao.zheng/.gradle/caches/transforms-1/files-1.1/constraint-layout-
1.1.3.aar/f44da5c361a1f52801511229596f72e7/jars/classes.jar
input file:/Users/chao.zheng/.gradle/caches/transforms-1/files-1.1/butterknife-
8.5.1.aar/9d5de52440cb778daab09db33955642f/jars/classes.jar
...
input
file:/Users/chao.zheng/sunday/OpenSpace/TasksPro/app/build/intermediates/classes/debug/android/support/constraint/R$id.cla
input
file:/Users/chao.zheng/sunday/OpenSpace/TasksPro/app/build/intermediates/classes/debug/android/support/constraint/R$style
input
file:/Users/chao.zheng/sunday/OpenSpace/TasksPro/app/build/intermediates/classes/debug/android/support/constraint/R$attr.
input
file:/Users/chao.zheng/sunday/OpenSpace/TasksPro/app/build/intermediates/classes/debug/android/arch/lifecycle/R.class
input file:/Users/chao.zheng/sunday/OpenSpace/TasksPro/app/build/intermediates/classes/debug/butterknife/R.class
---------------------------------------------------
output file:/Users/chao.zheng/sunday/OpenSpace/TasksPro/app/build/intermediates/transforms/dexBuilder/debug 输⼊⽂件⽐较多,中间省略了⼀部分,但是还是⽐较明显的看出输⼊⽂件分为两种类型:
1、依赖库的jar⽂件;
2、intermediates/classes/debug/⽬下的class⽂件(即本项⽬产⽣的class⽂件)。
输出⽂件:
1、编号0-16的jar包;
2、本项⽬的class⽂件⽣成的dex⽂件。
源码
主要代码逻辑
DexArchiveBuilderTransform.java类中的transform()⽅法:
public void transform(@NonNull TransformInvocation transformInvocation)
throws TransformException, IOException, InterruptedException {
...
try {
// 1、遍历输⼊
for (TransformInput input : Inputs()) {
/
/ 2、输⼊的类型是Directory,调⽤convertToDexArchive()⽅法。
for (DirectoryInput dirInput : DirectoryInputs()) {
logger.verbose("Dir input %s", File().toString());
convertToDexArchive(
dirInput,
outputProvider,
transformInvocation.isIncremental());
}
// 3、输⼊类型是Jar,则调⽤processJarInput⽅法。
for (JarInput jarInput : JarInputs()) {
logger.verbose("Jar input %s", File().toString());
List dexArchives =
processJarInput(
transformInvocation.isIncremental(),
jarInput,
outputProvider);
cacheableItems.putAll(jarInput, dexArchives);
}
}
...
}
通过代码分析,知道transform是遍历所有的输⼊⽂件,分为两种类型来处理:
1、输⼊的类型是Directory,调⽤convertToDexArchive()⽅法,接着调⽤了launchProcessing()⽅法,最终调⽤DxDexArchiveBuilder的dex()⽅法,代码如下:
// 1、通过⽅法应该就能知道,这个⽅法就是将class转变成dex的。
public void dex(String relativePath, ByteArray classBytes, DexArchive output)
throws IOException {
// Copied from dx, from com.android.dxmand.dexer.Main
DirectClassFile cf = new DirectClassFile(classBytes, relativePath, true);
cf.setAttributeFactory(StdAttributeFactory.THE_ONE);
// 2、DexFile obj
// starts the actual translation and writes the content to the dex file
// specified
DexFile dexFile = new DexOptions());
// Copied from dx, from com.android.dxmand.dexer.Main
ClassDefItem classDefItem =
cf,
null,
dexFile);
dexFile.add(classDefItem);
if (outStorage != null) {
ByteArrayAnnotatedOutput byteArrayAnnotatedOutput = dexFile.writeTo(outStorage);
output.addFile(
ClassFileEntry.withDexExtension(relativePath),

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。