作者

大家好,我叫祥子;

自己15年结业于广东药科大学,于2018年8月加入37手游安卓团队,曾经上任于网易担任安卓开发工程师;

现在是37手游安卓团队负责人,除日常团队相关管理外,闲暇喜爱专研安卓相关技能,因为一直深信 “技能管理” 是一定要继续关注技能,坚持对技能的热情,这样才不会是空中楼阁…

背景

(1)正常App开发中,在写Activity或许Fragment时,无法避免的会用到findViewById这类的代码,然后强制类型转换出咱们所需求的控件类型,说实话,对于寻求代码简洁,高可读,而且想偷懒的程序员来说,写这样的重复代码,几乎便是灾难;

所以咱们会用到控件注解结构(如:butterknife),来处理上面的困扰,具体细节网上很多博客能够查到(如:butterknife系列),这儿就不打开讲。

(2)游戏发行SDK开发中,咱们并不能愉快的直接运用网上的结构,为什么?接下来咱们来看看;

安卓游戏发行-控件注解框架-关键点1

上面图是发行职业的常规流程,其中能够看到:

  • 游戏研制商接完咱们的SDK,给到咱们的是一个apk(这儿咱们叫它母包);
  • 然后咱们发行方需求进行从头(二次)打包,也便是《反编译母包-预备途径和SDK材料-交融-回编译》,从头输出apk上架(这儿咱们叫它途径包);
  • 最终是把途径包上架,用户下载运用

假设咱们游戏发行商SDK中,用经过ID找控件(findViewById方法),走上面的流程之后,输出的途径包,会有找不到控件溃散的反常,具体原因如下:

  • 接入咱们发行商的SDK输出母包,这个SDK中已经有findViewById(R.id.sqBtn),这次编译假定ID的值为0x7f070001,而且对应的资源类为R1类

  • 从头(二次)打包-反编译母包,此时根据resource.arsc文件发生public.xml文件,这个public.xml会固定住ID的值,也便是R.id.sqBtn的值一直为0x7f070001(resource.arsc文件和public.xml文件不了解的同学能够看以前的博客)

  • 从头(二次)打包-预备途径和SDK材料,关于《途径和SDK材料》这儿不打开,信任发行的同学是知道的,这儿在生成《途径和SDK材料》的时分,其实是经过了编译和从头生成了R类的,假定这次生成的R.id.sqBtn的值为0x7f070002,而且对应的资源类为R2类

  • 从头(二次)打包-交融/回编译,交融进程中,会把R2类掩盖R1类

  • 从头(二次)打包-途径包,因为包以前的R1类变为了R2类,R.id.sqBtn的值变为了0x7f070002;然后app运转,到resource.arsc中查找资源的时分,因为resource.arsc中的值为以前的0x7f070001(因public.xml固定作用),值不一样导致程序反常。

职业遍及的方案

因为不能运用findViewById去找控件,所以大部分状况下,发行职业安卓找控件一般采纳的是getIdentifier的方法;例如:getIdentifier(“sqBtn”, ”id” ,pkgName),这样做的坏处是:

  • 效率方面,程序员编码的效率有提高空间(没有编码的自动提示等)

  • 隐患方面,编译的时分不像id写法那样,会查看资源是否存在,假设不小心单词写错,然后又没有测试出来,会呈现毁灭性的溃散,导致线上事端

要处理的2个要害点

(1)要害点一:既然体系的R.id在发行流程中不能用,只能用getIdentifier(“sqBtn”, ”id” ,pkgName)的方法,那么咱们就要看看怎么使用资源名 +getIdentifier, 经过某种方法转换为相似ID那样能够提示编程,怎么办呢?

37手游有这么一句话 “方法总比困难多”,经过gradle的插件能力能够制造出自己的SqR,这儿咱们叫它《克己资源SqR技能》

(2)要害点二:有了契合咱们发行范畴的SqR资源了,那么接下来便是相似butterknife那样使用注解技能完成控件注入结构,这儿咱们叫它 《自定义注解技能》

补白:因为触及的知识点比较多,所以会分开来讲,本章主要讲要害点1

要害点1-克己资源SqR技能(这是个Gradle插件)

运用作用

1)编译时分校验:

安卓游戏发行-控件注解框架-关键点1

2)编码时分提示:

安卓游戏发行-控件注解框架-关键点1

运用简介

1)新增加资源,如:图片/字符串等(一般状况是批量先弄好,再走到第2步)

安卓游戏发行-控件注解框架-关键点1

2)生成SqR资源(除了这样点击之外,也能够弄成AS的快捷键愈加方便运用)

安卓游戏发行-控件注解框架-关键点1

3)愉快的运用

安卓游戏发行-控件注解框架-关键点1

完成流程

1)首先需求先构建一个gradle工程,因为这个不是本章要点,故不在这儿打开;不了解的同学能够去查相关材料,这儿推荐一个深入浅出的例子,戳这儿>>>

2)然后是开端写咱们的生成SqR代码了,写之前先看下咱们要构造的文件最终容貌:

安卓游戏发行-控件注解框架-关键点1

写的中心思维是经过对R.java(工程为app模块)文件或许R.txt(工程为lib模块)文件进行改造

  • 假设工程为app模块,则经过R.java文件改,要害点主要3个,具体看下图:

安卓游戏发行-控件注解框架-关键点1

要害代码简析:

//rPackage:取得包名,以便获取途径 
//例子:com.sq.mobile.sqinject_gradle_plugin 
def rPackage = this.getPackageName(variant)println(rPackage)rPackage = rPackage.replace(".", "/")
//取得资源任务(the Android Resources processing task)
def variantOutput = variant.outputs.first()
def processResources = variantOutput.processResourcesProvider.get()
def rFiles = project.files(processResources.textSymbolOutputFile).builtBy(processResources)
//取得R.txt途径
//R.txt途径:sqinjectgradleplugin/app/build/intermediates/symbols/debug/R.txt
def RFilePath = rFiles.singleFile.absolutePath
//取得输出途径
//sqinjectgradleplugin/app/build/generated/not_namespaced_r_class_sources/debug/r
def outputDir = processResources.getSourceOutputDir()
//将原先的R文件的int换成String,并将其值运用变量名赋值
//tempFile = sqinjectgradleplugin/app/build/generated/not_namespaced_r_class_sources/debug/r/com/sq/mobile/sqinject_gradle_plugin/R.javaFile 
tempFile = new File(outputDir.absolutePath + File.separator + rPackage + File.separator + "R.java");
println("R file path: " + tempFile.absolutePath)
rFileContent = tempFile.textPattern 
pattern = Pattern.compile("public static(.*?) int (.*?)=(.*?);")
Matcher matcher = pattern.matcher(rFileContent);
while (matcher.find()) {    
  String replace = "public static final String " + matcher.group(2) + " = "" + matcher.group(2) + "";";    
  rFileContent = rFileContent.replaceAll(matcher.group(), replace)
}
rFileContent = rFileContent.replaceAll("class R", "class SqR")
  • 假设工程为lib模块,则经过R.txt文件改,要害点在于把下图进行规整,构建咱们要的文件格局

安卓游戏发行-控件注解框架-关键点1

要害代码简析:

安卓游戏发行-控件注解框架-关键点1

源码

请戳这儿>>>

总结

文章主要介绍了控件注入结构的要害点1,使用插件方法完成getIdentifier的ID化;

下一篇将介绍要害点2,使用注解技能完成SqR的注解运用,最终完成相似butterknife结构

;这个结构现在在咱们内部已经广泛运用,它命名为《SqInject》结构,现在申请专利中;

后续咱们除了会讲解要害点2之外,会一并把结构开源出来,敬请期待>>>

欢迎沟通

进程中有问题或许需求沟通的同学,能够扫描二维码加老友,然后进群进行问题和技能的沟通等;

安卓游戏发行-控件注解框架-关键点1