Android构建流程——篇四

本文详细解析了Android构建过程中的关键任务,包括generateDebugResValues(生成自定义资源值)、generateDebugResources(空任务)、mergeDebugResources(合并资源)和createDebugCompatibleScreenManifests(创建兼容屏幕清单)。mergeDebugResources任务中,详细探讨了资源的合并、DataMerger的mergeData方法,以及databinding、png crunching和aapt2的处理。createDebugCompatibleScreenManifests任务则涉及生成适配多屏幕的清单文件。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Task9 generateDebugResValues

1. input/ouput

taskName:generateDebugResValues
=========================================================
output:/Users/dingbaosheng/work/mockuai/project/AndroidGradleTaskDemo/app/build/generated/res/resValues/debug

简单的说该任务就是生成一个generated.xml文件,里面包含了在build.gradle文件中自定义的资源属性

  1. 配置自定义资源属性
    在这里插入图片描述
  2. 输出xml文件结构
    在这里插入图片描述

2. 核心类(GenerateResValues)

public class GenerateResValues extends AndroidBuilderTask {
   
	@TaskAction
    void generate() throws IOException, ParserConfigurationException {
   
        File folder = getResOutputDir();
		
		//1. 读取build.gradle中自定义的资源配置数据项
        List<Object> resolvedItems = getItems();
		
		//2. 如果未自定义,清空旧数据
        if (resolvedItems.isEmpty()) {
   
            FileUtils.cleanOutputDir(folder);
        } else {
   
        	//如果自定义了,将自定义资源数据项交给资源值生成器对象
            ResValueGenerator generator = new ResValueGenerator(folder);
            generator.addItems(getItems());
			
			//3. 生成generated.xml
            generator.generate();
        }
    }
}

代码看流程清晰明了,关键代码就是将自定义属性(支持12种类型属性哦)写入到xml文件中,其实现细节集中在类ResValueGenerator.generater中;内部主要使用DOM API来实现,具体不再详细说明,贴下实现代码

public class ResValueGenerator {
   

    public static final String RES_VALUE_FILENAME_XML = "generated.xml";

    private static final List<ResourceType> RESOURCES_WITH_TAGS = ImmutableList.of(
            ResourceType.ARRAY,
            ResourceType.ATTR,
            ResourceType.BOOL,
            ResourceType.COLOR,
            ResourceType.DECLARE_STYLEABLE,
            ResourceType.DIMEN,
            ResourceType.FRACTION,
            ResourceType.INTEGER,
            ResourceType.PLURALS,
            ResourceType.STRING,
            ResourceType.STYLE);
	/**
     * Generates the resource files
     */
    public void generate() throws IOException, ParserConfigurationException {
   
        File pkgFolder = getFolderPath();
        if (!pkgFolder.isDirectory()) {
   
            if (!pkgFolder.mkdirs()) {
   
                throw new RuntimeException("Failed to create " + pkgFolder.getAbsolutePath());
            }
        }

        File resFile = new File(pkgFolder, RES_VALUE_FILENAME_XML);

        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
        factory.setNamespaceAware(true);
        factory.setValidating(false);
        factory.setIgnoringComments(true);
        DocumentBuilder builder;

        builder = factory.newDocumentBuilder();
        Document document = builder.newDocument();
		
		//创建根节点resources
        Node rootNode = document.createElement(TAG_RESOURCES);
        document.appendChild(rootNode);
		
		//添加子节点,此处就是添加些注释说明
        rootNode.appendChild(document.createTextNode("\n"));
        rootNode.appendChild(document.createComment("Automatically generated file. DO NOT MODIFY"));
        rootNode.appendChild(document.createTextNode("\n\n"));
		
		//遍历自定义资源属性
        for (Object item : mItems) {
   
            if (item instanceof ClassField) {
   
                ClassField field = (ClassField)item;

                ResourceType type = ResourceType.getEnum(field.getType());
				
				//判断是否是通用的11种类型中一种
                boolean hasResourceTag = (type != null && RESOURCES_WITH_TAGS.contains(type));
				
				//如果不是通用的资源类型,则生成<item>标签节点
                Node itemNode = document.createElement(hasResourceTag ? field.getType() : TAG_ITEM);
                Attr nameAttr = document.createAttribute(ATTR_NAME);

                nameAttr.setValue(field.getName());
                itemNode.getAttributes().setNamedItem(nameAttr);
				
				
                if (!hasResourceTag) {
   
                	//如果是item标签,需要设置其type、name属性值
                	//eg:<item type="id" name="button_ok" />
                    Attr typeAttr = document.createAttribute(ATTR_TYPE);
                    typeAttr.setValue(field.getType());
                    itemNode.getAttributes().setNamedItem(typeAttr);
                }

                if (type == ResourceType.STRING) {
   
                	//如果是string资源,添加traslatable属性,使其设备统一使用该字段,和系统语言等无关
                    Attr translatable = document.createAttribute(ATTR_TRANSLATABLE);
                    translatable.setValue(VALUE_FALSE);
                    itemNode.getAttributes().setNamedItem(translatable);
                }

                if (!field.getValue().isEmpty()) {
   
                    itemNode.appendChild(document.createTextNode(field.getValue()));
                }

                rootNode.appendChild(itemNode);
            } else if (item instanceof String) {
   
                rootNode.appendChild(document.createTextNode("\n"));
                rootNode.appendChild(document.createComment((String) item));
                rootNode.appendChild(document.createTextNode("\n"));
            }
        }

        String content;
        try {
   
            content = XmlPrettyPrinter.prettyPrint(document, true);
        } catch (Throwable t) {
   
            content = XmlUtils.toXml(document);
        }
		
		//写文件
        Files.write(content, resFile, Charsets.UTF_8);
    }
}    

支持的自定义资源属性类型

序号 类型
1 array
2 attr
3 bool
4 color
5 declare-styleable
6 dimen
7 fraction
8 integer
9 plurals
10 string
11 style
12 item

Task10 generateDebugResources

属于空task直接忽略

Task11 mergeDebugResources

合并资源任务

1. input/ouput

taskName:mergeDebugResources
input:/Users/apple/.gradle/caches/transforms-1/files-1.1/aapt2-3.2.0-4818971-osx.jar/c5355294e416159d9559f45d46460f7d/aapt2-3.2.0-4818971-osx
input:/Users/apple/work/project/AndroidGradleTaskDemo/app/build/generated/res/resValues/debug
input:/Users/apple/.gradle/caches/transforms-1/files-1.1/appcompat-v7-26.1.0.aar/2774ea4f1cf1e83a6ad8e8d3c8b463b6/res
input:/Users/apple/.gradle/caches/transforms-1/files-1.1/constraint-layout-1.1.3.aar/f43c0ba95b6494825ed940fc4f04662b/res
input:/Users/apple/.gradle/caches/transforms-1/files-1.1/support-media-compat-26.1.0.aar/53ab5ad72634f3497309a8788f3ca200/res
input:/Users/apple/.gradle/caches/transforms-1/files-1.1/support-compat-26.1.0.aar/4ec3c1c46e5bad9ac3b91f45a2afec3e/res
input:/Users/apple/work/project/AndroidGradleTaskDemo/app/build/generated/res/rs/debug
input:/Users/apple/work/project/AndroidGradleTaskDemo/app/src/main/res
input:/Users/apple/work/project/AndroidGradleTaskDemo/app/src/debug/res
=========================================================
output:/Users/apple/work/project/AndroidGradleTaskDemo/app/build/intermediates/blame/res/debug
output:/Users/apple/work/project/AndroidGradleTaskDemo/app/build/generated/res/pngs/debug
output:/Users/apple/work/project/AndroidGradleTaskDemo/app/build/intermediates/incremental/mergeDebugResources
output:/Users/apple/work/project/AndroidGradleTaskDemo/app/build/intermediates/res/merged/debug

先来一张总流程图吧,先把握主线;文字描述的不一定有图清楚
在这里插入图片描述

xml -> drawable 、string 、color、anim、layout、value
layout、generated
png
先看输入好了,可以很清楚看到输入都是项目依赖的库的res文件以及本身结构的res文件

输出路径 产物 备注 所在类
app/build/intermediates/blame/res/debug 1. 日志文件 2. 资源文件和编译后产物的映射表文件
app/build/generated/res/pngs/debug 资源文件vector、png xxx
app/build/intermediates/incremental/mergeDebugResources 1、merged.dir 存放合并资源文件的地方2、stripped.dir 3、compile-file-map.properties 资源和编译产物映射表 4、merger.xml 合并文件 MergedResourceWriter
app/build/intermediates/res/merged/debug flat文件 AAPT2编译的产物,也就是本上图的重点产物 MergedResourceWriter

app/build/intermediates/incremental/mergeDebugResources

  1. merged.dir
  2. stripped.dir
  3. compile-file-map.properties
  4. merger.xml

2. 核心类(MergeResources)

@CacheableTask
public class MergeResources extends IncrementalTask {
   
	
	@Override
    protected void doFullTaskAction() throws IOException, JAXBException {
   
        ResourcePreprocessor preprocessor = getPreprocessor();

        // this is full run, clean the previous outputs
        File destinationDir = getOutputDir();
        FileUtils.cleanOutputDir(destinationDir);
        if (dataBindingLayoutInfoOutFolder != null) {
   
            FileUtils.deleteDirectoryContents(dataBindingLayoutInfoOutFolder);
        }

        List<ResourceSet> resourceSets = getConfiguredResourceSets(preprocessor);

        // create a new merger and populate it with the sets.
        ResourceMerger merger = new ResourceMerger(minSdk.get());
        MergingLog mergingLog = null;
        if (blameLogFolder != null) {
   
            FileUtils.cleanOutputDir(blameLogFolder);
            mergingLog = new MergingLog(blameLogFolder);
        }

        try (ResourceCompilationService resourceCompiler =
                getResourceProcessor(
                        aaptGeneration,
                        getBuilder(),
                        aapt2FromMaven,
                        workerExecutorFacade,
                        crunchPng,
                        variantScope,
                        mergingLog,
                        flags,
                        processResources)) {
   

            for (ResourceSet resourceSet : resourceSets) {
   
                resourceSet.loadFromFiles(getILogger());
				//1. 添加资源
                merger.addDataSet(resourceSet);
            }

            MergedResourceWriter writer =
                    new MergedResourceWriter(
                            workerExecutorFacade,
                            destinationDir,
                            getPublicFile(),
                            mergingLog,
                            preprocessor,
                            resourceCompiler,
                            getIncrementalFolder(),
                            dataBindingLayoutProcessor,
                            mergedNotCompiledResourcesOutputDirectory,
                            pseudoLocalesEnabled,
                            getCrunchPng());
			//2. 执行资源合并操作
            merger.mergeData(writer, false /*doCleanUp*/);

            if (dataBindingLayoutProcessor != null) {
   
                dataBindingLayoutProcessor.end();
            }
			
			//3. 生成merger.xml文件
            // No exception? Write the known state.
            merger.writeBlobTo(getIncrementalFolder(), writer, false);
        } catch (MergingException e) {
   
            System.out.println(e.getMessage());
            merger
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值