Android APT如何实现控件注入框架SqInject的方法

  介绍

本篇内容介绍了“Android APT如何实现控件注入框架SqInject的方法”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!

背景

在游戏发行中,经常需要切包,如果直接使用R.id.xxx,在回编译时,由于resources.arsc会重新编译,R类中的id值和resources.arsc中的对应关系会异常,导致程序异常。我们有两种解决方法。

一种是在切包过程中纠正R类的值,实现方案具体介绍可以查看

游戏发行切包资源索引冲突解决方案,链接如下:

//www.yisu.com/article/207579.htm

另一种解决方案则是使用getIdentifier获取资源id,放弃使用R类,这种方式中,编码较为麻烦,并且getIdentifier中需要写的是字符串,容易写错,并且编译过程中是发现不了的。基于这种情况,我们开发了基于getIdentifier的控件注入框架

一、恰当的技术简介

1,恰当的定义

APT(注释处理工具)即注解处理器,是一种处理注解的工具,确切的说它是javac的一个工具,它用来在编译时扫描和处理注解。注解处理器以Java代码作为输入,生成。java文件作为输出

2,注解定义

1,注解是一种能被添加到java代码中的元数据,类,方法,变量,参数和包都可以用注解修饰。

2,注解对于它所修饰的代码没有直接的影响

3,恰当的原理简介

 Android APT如何实现控件注入框架SqInject的方法

注解处理是在编译阶段执行的,它的原理就是读入java源代码,解析注解,然后生成新java的代码。新生成的java代码最后被编译成java字节码,注解解析器(注解处理器)不能改变读入的java类,比如不能加入或删除java方法

二、APT实战使用

1, SqInject框架来源

在手游发行中,经常需要切包,将游戏接完SDK1的包,通过反编译,替换smali文件及其他资源文件的方式,替换为渠道SDK2的渠道包。在这个反编译回编译的过程中,资源索引ID(即R类和资源。arsc中的ID映射关系)会发生冲突导致程序异常,即不做特殊处理的话,渠道SDK及发行SDK是不能直接使用R类的,要使用getIdentifier获取资源ID

要求在程序中使用getIdentifier,在开发过程中是比较麻烦的事情。在这样的条件下,我们也无法使用如butterknife这样的框架,因此,我们模仿butterknife开发了一套基于getIdentifier的控件注入框架SqInject。下面介绍SqInject的实现,先来看下简单使用哈

public  class  MainActivity  extends  AppCompatActivity  {      ,//绑定ID   ,@BindView (SqR.id.tv)   ,TextView 你好;      ,@Override   ,protected  void  onCreate (Bundle  savedInstanceState), {   ,super.onCreate (savedInstanceState);   ,setContentView (R.layout.activity_main);   ,SqInject.bind(这个);   ,Log.e (“SqInject", hello.getText () .toString ());   ,}      ,//绑定点击事件   ,@OnClick (SqR.id.tv)   ,public  void 单击(View 视图),{   ,Intent  Intent =, new 意图(TestActivity.class MainActivity.this也);   ,startActivity(意图);   ,}   }

2, SqInject的实现原理

2.1,注解处理器模块实现

上文说到恰当的常用于生成代码,在SqInject中恰当的注解处理环节中,流程如下图所示:

 Android APT如何实现控件注入框架SqInject的方法

在编译过程中扫描注解,生成Java代码,而后再次编译

在SqInject代码中,实现如下:

@AutoService (Processor.class)   @SupportedSourceVersion (SourceVersion.RELEASE_7)   public  class  SqInjectProcessor  extends  AbstractProcessor  {      ,……      ,//核心方法   ,@Override   ,public  boolean 过程(Set<?, extends  TypeElement>,,, RoundEnvironment  roundEnvironment), {   ,//控件类注解解析,ResChecker检查资源id合法性,合法则生成“类名+美元ViewBinder类,否则编译失败   ,BindViewBuilder  BindViewBuilder =, new  BindViewBuilder (mResChecker, roundEnvironment,还以为,mElementUtils, mTypeUtils,, mFiler,, mMessager);   ,bindViewBuilder.build ();   ,//id类注解解析,ResChecker检查资源id合法性,合法则生成“类名+美元IdBinder类“,否则编译失败   ,BindIdsBuilder  BindIdsBuilder =, new  BindIdsBuilder (mResChecker, roundEnvironment,还以为,mElementUtils, mTypeUtils,, mFiler,, mMessager);   ,bindIdsBuilder.build ();   ,return 假;   ,}   ,   }

Android APT如何实现控件注入框架SqInject的方法