乡下人产国偷v产偷v自拍,国产午夜片在线观看,婷婷成人亚洲综合国产麻豆,久久综合给合久久狠狠狠9

  • <output id="e9wm2"></output>
    <s id="e9wm2"><nobr id="e9wm2"><ins id="e9wm2"></ins></nobr></s>

    • 分享

      Android進階

       quasiceo 2018-09-06

      前言

      APT的學習要花點時間去掌握和實踐的,短時間內只能掌握知識點,更多的是在實戰(zhàn)中去實踐。其實,APT就是一種工具而已,只要用多了,自然就會熟練了,不過要想實踐之前,還是必須把基礎知識學好才能實戰(zhàn)進入開發(fā)。文章會從基礎用例講解知識點,然后再通過實戰(zhàn)進行實踐

      APT簡介

      APT(Annotation Processing Tool)是一種處理注解的工具,它會對源代碼中的注解進行額外的處理,比如在編譯時生成一些重復性操作的Java代碼,或者不需要程序員去關心的Java代碼等。在使用APT的過程中會涉及到下面兩個第三方庫的使用

      1. AutoService:這個庫的主要作用是注冊注解,并對其生成META-INF的配置信息
      2. JavaPoet:這個庫的主要作用是幫助我們通過類調用的形式來生成Java代碼

      APT主要過程包括初始化過程和注解處理過程

      1. 初始化過程:獲取APT提供的工具類,為后面的注解處理提供幫助
      2. 注解處理過程:獲取注解的元素,對元素進行額外處理,可用JavaPoet生成Java代碼

      APT流程

      1、定義注解

      該注解是可以在我們的項目中使用到的,且規(guī)定為注解元素的類型為Type,和在編譯時生效

      @Target(ElementType.TYPE)
      @Retention(RetentionPolicy.RUNTIME)
      public @interface ModuleWrapper {
      
      }
      • 1
      • 2
      • 3
      • 4
      • 5

      2、定義Processor

      Processor會在編譯期對注解進行解析,取出對應的元素進行處理。至于AutoService則是固定的寫法,加個注解即可

      @AutoService(Processor.class)
      public class ModuleProcessor extends AbstractProcessor {
      
          private Filer filerUtils; // 文件寫入
          private Elements elementUtils; // 操作Element工具類
          private Messager messagerUtils; // Log 日志
          private Map<String, String> options; // 額外配置參數(shù)
      
          @Override
          public synchronized void init(ProcessingEnvironment processingEnvironment) {
              super.init(processingEnvironment);
      
              filerUtils = processingEnvironment.getFiler();
              elementUtils = processingEnvironment.getElementUtils();
              messagerUtils = processingEnvironment.getMessager();
              options = processingEnvironment.getOptions();
          }
      
          @Override
          public Set<String> getSupportedAnnotationTypes() {
              Set<String> types = new LinkedHashSet<>();
              types.add(ModuleWrapper.class.getCanonicalName());
              return types;
          }
      
          @Override
          public boolean process(Set<? extends TypeElement> set, RoundEnvironment roundEnvironment) {
              initModuleMap(roundEnvironment);
              return false;
          }
      
          private void initModuleMap(RoundEnvironment roundEnv) {
              //獲取對應的注解元素
              Set<? extends Element> set = roundEnv.getElementsAnnotatedWith(ModuleWrapper.class);
              for (Element element : set) {
                  //如果是個類
                  if (element.getKind() == ElementKind.CLASS) {
                      //獲取類名
                      String clzName = element.getSimpleName().toString();
                      //對元素進行處理,可用javapoet生成Java代碼
                      ......
                  } else {
                      messagerUtils.printMessage(Diagnostic.Kind.NOTE, "only support class");
                  }
              }
          }
      }
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21
      • 22
      • 23
      • 24
      • 25
      • 26
      • 27
      • 28
      • 29
      • 30
      • 31
      • 32
      • 33
      • 34
      • 35
      • 36
      • 37
      • 38
      • 39
      • 40
      • 41
      • 42
      • 43
      • 44
      • 45
      • 46
      • 47

      3、AbstractProcessor實現(xiàn)方法介紹

      1. init():初始化過程,可通過初始化方法獲取各種工具類
      2. process():注解處理過程,可通過獲取注解元素后,對注解元素進行額外處理
      3. getSupportedAnnotationTypes():獲取需要解析的注解類型

      APT知識點

      1、初始化介紹

      APT初始化階段為init方法的調用,我們可以使用ProcessingEnvironment獲取一些實用類以及獲取選項參數(shù)等

      方法 說明
      getElementUtils() 返回實現(xiàn)Elements接口的對象,用于操作元素的工具類
      getFiler() 返回實現(xiàn)Filer接口的對象,用于創(chuàng)建文件、類和輔助文件
      getMessager() 返回實現(xiàn)Messager接口的對象,用于報告錯誤信息、警告提醒
      getOptions() 返回指定的參數(shù)選項
      getTypeUtils() 返回實現(xiàn)Types接口的對象,用于操作類型的工具類

      2、Element介紹

      Element是操作元素最主要的類,可通過getElementsAnnotatedWith獲取Element的元素,經(jīng)過getKind()判斷元素的類型后,可強制轉換成對應的類型,在對應的類型中有著不同的方法可以調用

      類型 說明
      ExecutableElement 表示類、接口的方法元素。包括構造方法、注解類型
      PackageElement 表示包元素。提供對有關包及其成員的信息的訪問
      TypeElement 表示類、接口元素。提供對有關類型及其成員的信息的訪問
      TypeParameterElement 表示類、接口、方法、構造方法的參數(shù)元素
      VariableElement 表示字段、enum、方法、構造方法參數(shù)、局部變量、異常參數(shù)

      ElementKind為元素的類型,元素的類型判斷不需要用instanceof去判斷,而應該通過getKind()去判斷對應的類型

      類型 說明
      PACKAGE
      ENUM 枚舉
      CLASS
      ANNOTATION_TYPE 注解
      INTERFACE 接口
      ENUM_CONSTANT 枚舉常量
      FIELD 字段
      PARAMETER 方法參數(shù)
      LOCAL_VARIABLE 局部變量
      METHOD 方法
      CONSTRUCTOR 構造方法
      TYPE_PARAMETER 類型參數(shù)

      3、TypeMirror介紹

      TypeMirror是一個接口,表示Java編程語言中的類型。這些類型包括基本類型、引用類型、數(shù)組類型、類型變量和null類型等等

      類型 說明
      ArrayType 表示數(shù)組類型
      DeclaredType 表示聲明類型(類或接口類型)
      ErrorType 表示異常類或接口類型
      ExecutableType 表示executable類型(方法、構造方法、初始化)
      NoType 表示在實際類型不適合的地方使用的偽類型
      NullType 表示null類型
      PrimitiveType 表示基本數(shù)據(jù)類型
      ReferenceType 表示引用類型
      TypeVariable 表示類型變量
      WildcardType 表示通配符類型參數(shù)

      TypeKind為類型的屬性,類型的屬性判斷不需要用instanceof去判斷,而應該通過getKind()去判斷對應的屬性

      類型 說明
      BOOLEAN 基本類型boolean
      INT 基本類型int
      LONG 基本類型long
      FLOAT 基本類型float
      DOUBLE 基本類型double
      VOID 對應于關鍵字void的偽類型
      NULL null類型
      ARRAY 數(shù)組類型
      PACKAGE 對應于包元素的偽類型
      EXECUTABLE 方法、構造方法、初始化

      這里需要注意的是,如果我們通過注解去獲取Class類型的值,如果獲取的Class未被編譯,則會拋出MirroredTypeException異常,此時我們需要通過try-catch語句在catch里去獲取我們所需要的類元素

      try {  
          annotation.value();//如果value為Class類型則會報異常
      } catch (MirroredTypeException mte) {
          DeclaredType classTypeMirror = (DeclaredType) mte.getTypeMirror();
          TypeElement classTypeElement = (TypeElement) classTypeMirror.asElement();//通過異常去獲取類元素
      }
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6

      4、Filer介紹

      Filer接口支持通過注解處理器創(chuàng)建新文件??梢詣?chuàng)建三種文件類型:源文件、類文件和輔助資源文件

      方法 說明
      createSourceFile 創(chuàng)建源文件
      createClassFile 創(chuàng)建類文件
      createResource 創(chuàng)建輔助資源文件

      5、Messager介紹

      Messager接口提供注解處理器用來報告錯誤消息、警告和其他通知的方式

      方法 說明
      printMessage 打印錯誤消息

      6、Options介紹

      通過getOptions()方法獲取選項參數(shù),在gradle文件中配置選項參數(shù)值

      android {
          defaultConfig {
              javaCompileOptions {
                  annotationProcessorOptions {
                      arguments = [ version : '1.0.0' ]
                  }
              }
          }
      }
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9

      通過ProcessingEnvironment去獲取對應的參數(shù)

      processingEnvironment.getOptions().get("version");
      • 1

      7、獲取注解元素

      通過RoundEnvironment接口去獲取注解元素,通過JavaPoet生成Java代碼

      方法 說明
      getElementsAnnotatedWith 返回注解元素的集合

      APT實戰(zhàn)

      下面通過APT的實戰(zhàn),進行對項目的模塊化劃分

      1、項目結構

      1. 創(chuàng)建Module,名為annotation,放置我們的注解類
      2. 創(chuàng)建Module,名為compiler,放置我們的注解處理類
      3. 主工程則直接依賴annotation和compiler

      注意事項:創(chuàng)建Module的時候,需要選擇java Lib,而不是Android Lib

      2、Gradle配置

      annotation的Module必須聲明Java編譯版本

      apply plugin: 'java-library'
      
      dependencies {
          implementation fileTree(dir: 'libs', include: ['*.jar'])
      }
      
      sourceCompatibility = "1.7"
      targetCompatibility = "1.7"
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8

      compiler的Module必須聲明Java編譯版本,且依賴于annotation和導入我們所需的庫

      apply plugin: 'java-library'
      
      dependencies {
          implementation fileTree(dir: 'libs', include: ['*.jar'])
      
          implementation project(':annotation')
          implementation 'com.google.auto.service:auto-service:1.0-rc2'
          implementation 'com.squareup:javapoet:1.7.0'
      }
      
      sourceCompatibility = "1.7"
      targetCompatibility = "1.7"
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12

      主工程必須通過依賴annotaion和compiler,由于我們只是在編譯期生效,可用annotationProcessor

      implementation project(':annotation')
      annotationProcessor project(':compiler')
      • 1
      • 2

      注意事項:定義編譯的jdk版本為1.7

      3、定義注解

      ModuleWrapper注解,表示需要加載的模塊

      @Target(ElementType.TYPE)
      @Retention(RetentionPolicy.RUNTIME)
      public @interface ModuleWrapper {
      
      }
      • 1
      • 2
      • 3
      • 4
      • 5

      IModule接口,表示當前類是一個模塊類

      public interface IModule {
          String getModuleName();
      }
      • 1
      • 2
      • 3

      4、定義Processor

      @AutoService(Processor.class)
      public class ModuleProcessor extends AbstractProcessor {
      
          private Map<String, ModuleInfo> moduleMaps = new HashMap<>();
      
          private Filer filerUtils; // 文件寫入
          private Elements elementUtils; // 操作Element 的工具類
          private Messager messagerUtils; // Log 日志
          private Map<String, String> options;
      
          @Override
          public synchronized void init(ProcessingEnvironment processingEnvironment) {
              super.init(processingEnvironment);
      
              filerUtils = processingEnvironment.getFiler();
              elementUtils = processingEnvironment.getElementUtils();
              messagerUtils = processingEnvironment.getMessager();
              options = processingEnvironment.getOptions();
          }
      
          @Override
          public Set<String> getSupportedAnnotationTypes() {
              Set<String> types = new LinkedHashSet<>();
              types.add(ModuleWrapper.class.getCanonicalName());
              return types;
          }
      
          @Override
          public boolean process(Set<? extends TypeElement> set, RoundEnvironment roundEnvironment) {
              try {
                  initModuleMap(roundEnvironment);
                  createModuleMap();
                  createModuleConstant();
              } catch (IOException e) {
                  e.printStackTrace();
              }
              return false;
          }
      
          /**
           * 通過注解元素獲取組件實體
           *
           * @param roundEnv
           */
          private void initModuleMap(RoundEnvironment roundEnv) {
              Set<? extends Element> set = roundEnv.getElementsAnnotatedWith(ModuleWrapper.class);
              for (Element element : set) {
                  if (element.getKind() == ElementKind.CLASS) {
                      String clzName = element.getSimpleName().toString();
                      if (moduleMaps.get(clzName) == null) {
                          ModuleInfo info = new ModuleInfo(elementUtils, (TypeElement) element);
                          moduleMaps.put(clzName, info);
                      }
                  } else {
                      messagerUtils.printMessage(Diagnostic.Kind.NOTE, "only support class");
                  }
              }
          }
      
          /**
           * 創(chuàng)建組件管理者
           *
           * @throws IOException
           */
          private void createModuleMap() throws IOException {
      
              FieldSpec fieldSpec = FieldSpec
                      .builder(ParameterizedTypeName.get(HashMap.class, String.class, IModule.class)
                              , "moduleMap", Modifier.PRIVATE)
                      .initializer("new HashMap<>()")
                      .build();
      
              CodeBlock.Builder codeBlock = CodeBlock.builder();
              for (String key : moduleMaps.keySet()) {
                  ModuleInfo info = moduleMaps.get(key);
                  codeBlock.addStatement("moduleMap.put($S ,new $T())", info.getFullClassName(),
                          ClassName.get(info.packageName, info.className));
              }
      
              MethodSpec initMethod = MethodSpec.methodBuilder("init")
                      .addModifiers(Modifier.PUBLIC)
                      .addCode(codeBlock.build())
                      .returns(TypeName.VOID)
                      .build();
      
              MethodSpec getMethod = MethodSpec.methodBuilder("get")
                      .addModifiers(Modifier.PUBLIC)
                      .addParameter(String.class, "cls")
                      .addStatement("return moduleMap.get(cls)")
                      .returns(IModule.class)
                      .build();
      
              ArrayList<MethodSpec> methods = new ArrayList<>();
              methods.add(initMethod);
              methods.add(getMethod);
      
              TypeSpec moduleFactory = TypeSpec.classBuilder("ModuleFactory")
                      .addModifiers(Modifier.PUBLIC)
                      .addMethods(methods)
                      .addField(fieldSpec)
                      .build();
      
              JavaFile javaFile = JavaFile.builder("com.hensen.compiler.processor", moduleFactory)
                      .build();
              javaFile.writeTo(filerUtils);
          }
      
          /**
           * 創(chuàng)建組件常量
           *
           * @throws IOException
           */
          private void createModuleConstant() throws IOException {
      
              TypeSpec.Builder moduleConstant = TypeSpec.classBuilder("ModuleConstant")
                      .addModifiers(Modifier.PUBLIC);
      
              for (String key : moduleMaps.keySet()) {
                  ModuleInfo info = moduleMaps.get(key);
                  FieldSpec fieldSpec = FieldSpec.builder(String.class, info.className)
                          .addModifiers(Modifier.PUBLIC, Modifier.STATIC, Modifier.FINAL)
                          .initializer("$S", info.getFullClassName())
                          .build();
                  moduleConstant.addField(fieldSpec);
              }
      
              JavaFile javaFile = JavaFile.builder("com.hensen.compiler.processor", moduleConstant.build())
                      .build();
              javaFile.writeTo(filerUtils);
          }
      }
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21
      • 22
      • 23
      • 24
      • 25
      • 26
      • 27
      • 28
      • 29
      • 30
      • 31
      • 32
      • 33
      • 34
      • 35
      • 36
      • 37
      • 38
      • 39
      • 40
      • 41
      • 42
      • 43
      • 44
      • 45
      • 46
      • 47
      • 48
      • 49
      • 50
      • 51
      • 52
      • 53
      • 54
      • 55
      • 56
      • 57
      • 58
      • 59
      • 60
      • 61
      • 62
      • 63
      • 64
      • 65
      • 66
      • 67
      • 68
      • 69
      • 70
      • 71
      • 72
      • 73
      • 74
      • 75
      • 76
      • 77
      • 78
      • 79
      • 80
      • 81
      • 82
      • 83
      • 84
      • 85
      • 86
      • 87
      • 88
      • 89
      • 90
      • 91
      • 92
      • 93
      • 94
      • 95
      • 96
      • 97
      • 98
      • 99
      • 100
      • 101
      • 102
      • 103
      • 104
      • 105
      • 106
      • 107
      • 108
      • 109
      • 110
      • 111
      • 112
      • 113
      • 114
      • 115
      • 116
      • 117
      • 118
      • 119
      • 120
      • 121
      • 122
      • 123
      • 124
      • 125
      • 126
      • 127
      • 128
      • 129
      • 130
      • 131

      5、組件實體

      組件實體保存著組件的信息

      public class ModuleInfo {
      
          public String packageName;
          public String className;
      
          public ModuleInfo(Elements elementUtils, TypeElement typeElement) {
              packageName = getPackageName(elementUtils, typeElement);
              className = getClassName(typeElement, packageName);
          }
      
          public String getClassName(TypeElement type, String packageName) {
              int packageLen = packageName.length() + 1;
              return type.getQualifiedName().toString().substring(packageLen)
                      .replace('.', '$');
          }
      
          public String getPackageName(Elements elementUtils, TypeElement classElement) {
              PackageElement packageElement = elementUtils.getPackageOf(classElement);
              return packageElement.getQualifiedName().toString();
          }
      
          public String getFullClassName() {
              return packageName + "." + className;
          }
      
          public String getClassName(){
              return className;
          }
      }
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21
      • 22
      • 23
      • 24
      • 25
      • 26
      • 27
      • 28
      • 29

      6、注解使用

      分別創(chuàng)建出禮物模塊和聊天模塊,聊天模塊增加發(fā)消息的方法

      @ModuleWrapper
      public class ChatModule implements IModule{
      
          @Override
          public String getModuleName() {
              return "ChatModule";
          }
      
          public void sendMessage() {
              Log.i("TAG", "Hi");
          }
      }
      
      @ModuleWrapper
      public class GiftModule implements IModule{
      
          @Override
          public String getModuleName() {
              return "GiftModule";
          }
      }
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21

      7、生成代碼

      在生成代碼之前需要gradle build,查看生成代碼。當然對于模塊來說,不僅有get()、還有add()、remove()等其他擴展功能,具體的就留給大家去操作

      public class ModuleFactory {
        private HashMap<String, IModule> moduleMap = new HashMap<>();
      
        public void init() {
          moduleMap.put("com.hensen.geneapt.GiftModule" ,new GiftModule());
          moduleMap.put("com.hensen.geneapt.ChatModule" ,new ChatModule());
        }
      
        public IModule get(String cls) {
          return moduleMap.get(cls);
        }
      }
      
      public class ModuleConstant {
        public static final String GiftModule = "com.hensen.geneapt.GiftModule";
      
        public static final String ChatModule = "com.hensen.geneapt.ChatModule";
      }
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18

      8、組件使用

      初始化組件的加載,通過工廠獲取對應的模塊進行操作

      public class MainActivity extends AppCompatActivity {
      
          @Override
          protected void onCreate(Bundle savedInstanceState) {
              super.onCreate(savedInstanceState);
              setContentView(R.layout.activity_main);
      
              ModuleFactory moduleFactory = new ModuleFactory();
              moduleFactory.init();
      
              ChatModule chatModule = (ChatModule) moduleFactory.get(ModuleConstant.ChatModule);
              chatModule.sendMessage();

        本站是提供個人知識管理的網(wǎng)絡存儲空間,所有內容均由用戶發(fā)布,不代表本站觀點。請注意甄別內容中的聯(lián)系方式、誘導購買等信息,謹防詐騙。如發(fā)現(xiàn)有害或侵權內容,請點擊一鍵舉報。
        轉藏 分享 獻花(0

        0條評論

        發(fā)表

        請遵守用戶 評論公約

        類似文章 更多