Android的路由框架一般都是基于注解做處理的,但是由于反射造成一定運行效率的損耗,所以我們會更青睞于編譯時注解的框架,也就是程序在編譯的時候通過處理注解生成Java代碼。那我們就先講一講注解,網上關于注解的講解有很多,我是看了這篇文檔 Java注解(Annotation),里面的講解很詳細,這里我就說說我們用到的東西。
@Retention(RetentionPolicy.CLASS)
@Target({ElementType.TYPE, ElementType.METHOD})
public @interface Router {
String[] value();
String[] stringParams() default "";
...
}
-
@Retention
表示該注解類型的注解保留的時長。當注解類型聲明中沒有@Retention元注解,則默認保留策略為RetentionPolicy.CLASS。關于保留策略(RetentionPolicy)是枚舉類型,共定義3種保留策略,如下表:
| RetentionPolicy | 含義 |
|---|---|
| SOURCE | 僅存在Java源文件,經過編譯器后便丟棄相應的注解 |
| CLASS | 存在Java源文件,以及經編譯器后生成的Class字節(jié)碼文件,但在運行時VM不再保留注解 |
| RUNTIME | 存在源文件、編譯生成的Class字節(jié)碼文件,以及保留在運行時VM中,可通過反射性地讀取注解 |
由于在編譯生成.class文件后我們沒有再使用注解,在這里使用@Retention(RetentionPolicy.SOURCE)也是可以的。驗證SOURCE和CLASS可以去./build/intermediates/classes/包名/*.class查看注解是否存在。
-
@Target
表示該注解類型的所使用的程序元素類型。當注解類型聲明中沒有@Target元注解,則默認為可適用所有的程序元素。如果存在指定的@Target元注解,則編譯器強制實施相應的使用限制。關于程序元素(ElementType)是枚舉類型,共定義8種程序元素,如下表:
| ElementType | 含義 |
|---|---|
| ANNOTATION_TYPE | 注解類型聲明 |
| CONSTRUCTOR | 構造方法聲明 |
| FIELD | 字段聲明(包括枚舉常量) |
| LOCAL_VARIABLE | 局部變量聲明 |
| METHOD | 方法聲明 |
| PACKAGE | 包聲明 |
| PARAMETER | 參數(shù)聲明 |
| TYPE | 類、接口(包括注解類型)或枚舉聲明 |
-
@interface聲明注解 -
String[] value();表示這個注解里可以存放什么類型值 -
default ""表示默認值
到這里關于Router要使用的注解基本語法已將講完啦[撒花]。
Router框架結構
-
annotation用于存放注解,Java模塊
apply plugin: 'java'
compileJava {
sourceCompatibility = '1.7'
targetCompatibility = '1.7'
}
-
compiler用于編寫注解處理器,Java模塊
apply plugin: 'java' //由于要使用javax包AndroidSdk是沒有的
compileJava {
sourceCompatibility = '1.7'
targetCompatibility = '1.7'
}
dependencies {
compile project(':annotation') //因為編寫注解處理器需要依賴相關注解,所以要依賴annotation模塊
compile 'com.google.auto.service:auto-service:1.0-rc2' //主要的作用是注解 Processor 類,并對其生成 META-INF 的配置信息
compile 'com.squareup:javapoet:1.7.0' //JavaPoet is a Java API for generating .java source files.
}
router用于給用戶提供使用的API, library模塊,依賴annotation模塊app
compile project(':router')
annotationProcessor project(':compiler')
在項目根目錄添加apt(注解處理工具):
dependencies {
...
classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8'
...
}
Router實現(xiàn)
注解最重要的就是注解處理器了,RouterProcessor會在編譯時期生成Java代碼。
@AutoService(Processor.class)
public class RouterProcessor extends AbstractProcessor {
private Filer filer;//用于創(chuàng)建Java文件
//初始化操作
@Override
public synchronized void init(ProcessingEnvironment processingEnv){
filer = processingEnv.getFiler();
}
//返回一個支持注解的set集合,也就是說想要處理的注解都要放到這個集合里面
@Override
public Set<String> getSupportedAnnotationTypes() {}
//返回處理器支持的最新版本
@Override
public SourceVersion getSupportedSourceVersion() {}
//處理注解,生成java文件就是在這個方法里
@Override
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {}
}
項目在組件化的時候會有很多模塊,通過Router是如何實現(xiàn)頁面跳轉的呢?于是有這么一個注解:
@Router("MainActivity")
public class MainActivity extends AppCompatActivity{}