一 gradle語法
Gradle環(huán)境
1.Android studio配置
?????? classpath'com.android.tools.build:gradle:3.5.0'
2.Gradle配置
?????? distributionUrl=https\://services.gradle.org/distributions/gradle-5.4.1-all.zip
什么是Gradle?
首先Gradle是一種構(gòu)建工具,它的出現(xiàn)讓工程有無限可能
Gradle核心是基于Groovy腳本語言,Groovy腳本基于Java且拓展了Java,因此Gradle需要依賴JDK和Groovy庫
?和ant、maven構(gòu)建有區(qū)別评架,gradle是一種編程思想
如何配置公共Gradle
????配置公共Gradle的作用:
? ????? 1.區(qū)別生產(chǎn)環(huán)境和測試環(huán)境
? ????? 2.抽離Android信息君丁,便于統(tǒng)一管理
? ????? 3.統(tǒng)一管理依賴的包
????步驟
? ? ? ? 1.在build.gradle同級目錄下新建一個gradle文件
? ? ? ? 2.通過ext代碼塊添加字典
ext {
username ="sunjchao"
? ? //生產(chǎn)/開發(fā)環(huán)境
? ? isRelease =true
? ? //gradle共用配置睛蛛,建立map存儲,對象名文判,key都可以自定義过椎,groovy糖果語法,非常靈活
? ? androidId = [
compileSdkVersion:29,
buildToolsVersion:"29.0.2",
minSdkVersion? ? :23,
targetSdkVersion :29,
versionCode? ? ? :1,
versionName? ? ? :"1.0"
? ? ]
appId = [
app? ? :"com.example.myapplication",
library:"com.example.library"
? ? ]
url = [
debug? :"debug",
release:"release"
? ? ]
supportLibrary ="28.0.0"
? ? dependencies = [
"appcomppat":"androidx.appcompat:appcompat:1.1.0",
"recycleview":"com.android.support:recyclerview-v7:${supportLibrary}",
"constraint":"androidx.constraintlayout:constraintlayout:1.1.3",
"design":"com.android.support:design:${supportLibrary}"
? ? ]
}
3.根目錄下的build.gradle頭部加入自定義config.gradle戏仓,相當于layout布局中加入include
????applyfrom:"config.gradle"
4.定義變量引用公共配置文件
? 定義? def androidId =rootProject.ext.androidId
? 引用? compileSdkVersion androidId.compileSdkVersion
????buildToolsVersion androidId.buildToolsVersion
? ? ?dependencies {
????????implementation fileTree(dir:'libs',include: ['*.jar'])
????????support.each { k, v -> implementation v }
????}
一些Gradle用法
def androidId =rootProject.ext.androidId
def appId =rootProject.ext.appId
def support =rootProject.ext.dependencies
def url =rootProject.ext.url
android {
compileSdkVersion androidId.compileSdkVersion
buildToolsVersion androidId.buildToolsVersion
defaultConfig {
applicationId appId.app
minSdkVersion androidId.minSdkVersion
targetSdkVersion androidId.targetSdkVersion
versionCode androidId.versionCode
versionName androidId.versionName
testInstrumentationRunner"androidx.test.runner.AndroidJUnitRunner"
? ? ? ? //開啟分包
? ? ? ? multiDexEnabledtrue
? ? ? ? //設(shè)置分包配置
? ? ? ? multiDexKeepFile file('multidex-config.txt')
//將svg圖片生成指定維度的png圖片
? ? ? vectorDrawables.generatedDensities('xxxhdpi','xxhdpi')
//使用support-v7兼容(5.0版本以上)
? ? ? ? vectorDrawables.useSupportLibrary =true
? ? ? ? //只保留指定和默認資源
? ? ? ? resConfigs('zh-rCN')
ndk {
abiFilters('armeabi-v7a')
}
//源集-設(shè)置源集的屬性疚宇,更改源集的Java目錄或者自由目錄等
? ? ? ? sourceSets {
main {
if (isRelease) {
//如果是組件化模式,需要單獨運行時
? ? ? ? ? ? ? ? ? ? manifest.srcFile'src/main/AndroidManifest.xml'
? ? ? ? ? ? ? ? ? ? java.srcDirs = ['src / main / java']
res.srcDirs = ['src / main / res']
resources.srcDirs = ['src / main / resources']
aidl.srcDirs = ['src / main / aidl']
assets.srcDirs = ['src / main / assets']
}else {
//集成化模式柜去,整個項目打包
? ? ? ? ? ? ? ? ? ? manifest.srcFile'src/main/AndroidManifest.xml'
? ? ? ? ? ? ? ? }
}
}
externalNativeBuild {
cmake {
cppFlags ""
? ? ? ? ? ? }
}
}
//signingConfigs一定要在buildTypes簽名
? ? signingConfigs {
debug {
//天坑:填錯了灰嫉,編譯不通過還找不到問題
? ? ? ? ? ? storeFile file("C:/Users/Administrator/.android/debug.keystore")
????????????storePassword "android"
? ? ? ? ? ? keyAlias "androiddebugkey"
? ? ? ? ? ? keyPassword "android"
? ? ? ? }
release {
//簽名文件
? ? ? ? ? ? storeFile file("D:/Sunjichao/.jks")
//簽名證書的類型
? ? ? ? ? ? storeType ""
? ? ? ? ? ? //簽名證書文件的密碼
? ? ? ? ? ? storePassword ""
? ? ? ? ? ? //簽名證書中的密鑰別名
? ? ? ? ? ? keyAlias ""
? ? ? ? ? ? //簽名證書中該密鑰的密碼
? ? ? ? ? ? keyPassword ""
? ? ? ? ? ? //是否開啟V2打包
? ? ? ? ? ? v2SigningEnabledtrue
? ? ? ? }
}
buildTypes {
debug {
//對構(gòu)建類型設(shè)置簽名信息
? ? ? ? ? ? signingConfig signingConfigs.debug
? ? ? ? ? ? buildConfigField("String","debug","\"${url.debug}\"")
}
release {
signingConfig signingConfigs.release
? ? ? ? ? ? buildConfigField("String","release","\"${url.release}\"")
minifyEnabled false
? ? ? ? ? ? proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'),'proguard-rules.pro'
? ? ? ? }
}
//AdbOptions可以對adb操作選項添加配置
? ? adbOptions {
//配置操作超時時間,單位毫秒
? ? ? ? timeOutInMs =5 *1000_0
? ? ? ? //adb install命令的選項配置
? ? ? ? installOptions'-r','-s'
? ? }
//對dx操作的配置嗓奢,接受一個DexOptions類型的閉包讼撒,配置由DexOptions提供
? ? dexOptions {
//配置執(zhí)行dx命令是為其分配最大的對內(nèi)存
? ? ? ? javaMaxHeapSize"4g"
? ? ? ? //配置是否預執(zhí)行dex Libraries工程,開啟后會提高增量構(gòu)建速度股耽,不過會影響clean構(gòu)建的速度根盒,默認為true
? ? ? ? preDexLibraries =false
? ? ? ? //配置是否開啟jumbo模式,代碼方法是超過65535需要強制開啟才能構(gòu)建成功
? ? ? ? jumboModetrue
? ? ? ? //配置Gradle運行dx命令時使用的線程數(shù)量
? ? ? ? threadCount8
? ? ? ? //配置multidex參數(shù)
? ? ? ? additionalParameters = [
'--multi-dex',//多dex分包
? ? ? ? ? ? ? ? '--set-max-idx-number=50000',//每個包內(nèi)方法數(shù)量上限
//'--main-dex-list=' + '/multidex-config.txt',//打包到主classes.dex的文件列表
? ? ? ? ? ? ? ? '--minimal-main-dex'
? ? ? ? ]
}
//執(zhí)行g(shù)radle lint命令即可運行l(wèi)int檢查物蝙,默認生成的報告在outputs/lint-results.html中
? ? lintOptions {
//遇到lint檢查錯誤會終止構(gòu)建炎滞,一般設(shè)置為false
? ? ? ? abortOnErrorfalse
? ? ? ? //將警告當作錯誤來處理,
? ? ? ? warningsAsErrorsfalse
? ? ? ? //檢查新的API
? ? ? ? check'NewApi'
? ? }
externalNativeBuild {
cmake {
path"src/main/cpp/CMakeLists.txt"
? ? ? ? ? ? version"3.10.2"
? ? ? ? }
}
}
dependencies {
implementation fileTree(dir:'libs',include: ['*.jar'])
support.each { k, v -> implementation v }
}
二 組件化項目詳細部署
組件化項目的意義
????1.面試技巧诬乞,在最短時間內(nèi)打動面試官
????2.開發(fā)需求册赛,不相互依賴,可以相互交互震嫉,任意組合森瘪,高度解耦
????3.團隊效率,分模塊打包票堵,測試扼睬,統(tǒng)一版本管理
Phone module和Android Library的區(qū)別
? ? 1.Phone module新建出可以獨立運行的模塊,可以看成是app悴势,配置為"applyplugin:'com.android.application'"
????有applicationId? 切換"com.android.library"
?????2.? Android Library新建出安桌庫窗宇,不能獨立運行。配置為"applyplugin:'com.android.library'"
????無applicationId 切換"com.android.application"
新建comment公共庫特纤、order訂單庫军俊、persional個人信息庫
Gradle搭建組件化項目環(huán)境
集成化開發(fā)模式,組件化開發(fā)模式
組件化開發(fā)的臨時代碼捧存,集成化打包動態(tài)隔離
組件化模式:子模塊可以獨立運行
集成化模式:打包整個項目apk蝇完,子模塊不可獨立運行
當需要發(fā)布正式版本時官硝,就需要集成化將各個子模塊打包成一個apk,而測試時,就分開打包短蜕,將各個模塊分開打包,通過配置gradle來實現(xiàn)切換
//生產(chǎn)/開發(fā)環(huán)境 動態(tài)切換組件化模式或者集成化模式
?1. isRelease =false
?2.? ?if (isRelease) {
????????applyplugin:'com.android.library'
????}else {
????????applyplugin:'com.android.application'
????}
? 3. if (!isRelease) {
????????applicationId appId.module
????}
動態(tài)隔離:將正式發(fā)布版本與測試版本的打包時隔離傻咖,便于開發(fā)過程中打包測試和發(fā)布朋魔。
//源集-設(shè)置源集的屬性,更改源集的Java目錄或者自由目錄等,方便測試環(huán)境卿操,打包不集成到正式環(huán)境
sourceSets {
main {
if (isRelease) {
//集成化模式警检,整個項目打包
? ? ? ? ? ? manifest.srcFile'src/main/AndroidManifest.xml'
? ? ? ? ? ? //release時,debug目錄下文件不需要合并到主工程
? ? ? ? ? ? java{
exclude'**/debug/**'
? ? ? ? ? ? }
}else {
//如果是組件化模式害淤,需要單獨運行時
? ? ? ? ? ? manifest.srcFile'src/main/debug/AndroidManifest.xml'
? ? ? ? }
}
}
三扇雕、子模塊間交互
module與module之間交互(包括跳轉(zhuǎn),傳參等)
方式
1.eventBus? eventBean非常多(一對一)窥摄,一對多就會混亂不堪镶奉、難以維護
2.反射反射技術(shù)可以成功,維護成本較高且容易出現(xiàn)高版本@hide限制崭放。
3.隱式意圖 維護成本還好哨苛,只是比較麻煩,需要維護Manifest中的action
4.BroadcastReceiver 需要動態(tài)注冊(7.0后)币砂,需求方發(fā)送廣播
5.類加載 需要準確的全類名路徑建峭,維護成本較高且容易出現(xiàn)人為失誤
6. ........
還有一種比較實用的方案,全局map,首先在公共庫里面創(chuàng)建一個PathBean class,里面有兩個屬性path和class
再創(chuàng)建一個全局路徑記錄器(RecordPathManager)决摧,在這里面創(chuàng)建全局的map,
private static Map>groupMap =new HashMap<>();
兩個函數(shù)1.將路徑信息加入全局mapjoinGroup(),2.根據(jù)路徑名獲得class對象亿蒸,達到跳轉(zhuǎn)的目的getTargetClass()
/**
* @param groupName 組名,"如order"
* @param pathName? 路徑名 "如com.example.module"
* @param clazz? ? 類對象,如"OrderActivity.class"
*/
public static void joinGroup(String groupName, String pathName, Class clazz) {
List list =groupMap.get(groupName);
? ? if (list ==null) {
list =new ArrayList<>();
? ? ? ? list.add(new PathBean(pathName, clazz));
? ? ? ? groupMap.put(groupName, list);
? ? }else {
for (PathBean pathBean:list){
if(!pathName.equals(pathBean.getPath())){
list.add(new PathBean(pathName,clazz));
? ? ? ? ? ? ? ? groupMap.put(groupName,list);
? ? ? ? ? ? }
}
}
}
/**
* 根據(jù)路徑名獲得class對象掌桩,達到跳轉(zhuǎn)的目的
* @param groupName
* @param pathName
* @return
*/
public static ClassgetTargetClass(String groupName,String pathName){
List list=groupMap.get(groupName);
? ? if(list==null)return null;
? ? for (PathBean pathBean:list){
if(pathName.equalsIgnoreCase(pathBean.getPath())){
return pathBean.getClazz();
? ? ? ? }
}
return null;
}
在application里面添加路徑信息边锁,以便初始化的時候可以加載全部的信息,
@Override
public void onCreate() {
super.onCreate();
? ? RecordPathManager.joinGroup("app","MainActivity", MainActivity.class);
? ? RecordPathManager.joinGroup("module","ModuleActivity", ModuleActivity.class);
? ? RecordPathManager.joinGroup("library","Library_Activity", Library_Activity.class);
}
在需要跳轉(zhuǎn)的地方這樣使用:
Class targeClass= RecordPathManager.getTargetClass("module","ModuleActivity");
if(targeClass==null){
Toast.makeText(Library_Activity.this,"targeClass為null",Toast.LENGTH_LONG).show();
}else {
Intent intent=new Intent(Library_Activity.this,targeClass);
? ? startActivity(intent);
}
這種方法同樣也有詬病的地方拘鞋,比如我的項目中有200個activity忘巧,在application中豈不是要添加200個map數(shù)據(jù)渣窜?
我們可以使用apt,注解處理器來簡化我們的使用過程
四 APT介紹和使用
什么時APT(Annotation Processing Tool)
是一種處理注釋的工具,他對源代碼文件進行檢測找出其中的Annitation,根據(jù)注解自動生成代碼券躁,如果想要自定義的注解處理器能夠正常運行,必須要通過APT工具來進行扛稽,也可以這樣理解柴灯,只有通過聲明APT工具后, 程序在編譯期間自定義的注解? ? 才能執(zhí)行宣旱。
通俗理解:根據(jù)規(guī)則仅父,幫我們生成代碼,生成類文件。?
開發(fā)環(huán)境兼容
Android studio 3.3.2+Gradle4.10.1(臨界版本)
Android studio 3.4.1+Gradle5.1.1(向下兼容)
Target該注解作用域的目標
Activity使用的布局文件注解???
@Target(ElementType.TYPE)? ? //接口笙纤,類耗溜,枚舉,注解
@Target(ElementType.FIELD)? ? //屬性省容、枚舉的常量
@Target(ElementType.METHOD)//方法
@Target(ElementType.PARAMETER)//方法參數(shù)
@Target(ElementType.CONSTRUCTOR)//構(gòu)造方法
@Target(ElementType.LOCAL_VARIABLE)//局部變量
@Target(ElementType.ANNOTATION_TYPE)//該注解使用在另一個注解中
@Target(ElementType.PACKAGE)? ? ? ? //包
@RETENTION(RetentionPolicy.RUNTIME)//注解會在class字節(jié)碼中存在抖拴,jvm加載時,可以通過反射獲得該注解中的內(nèi)容腥椒。
生命周期 SOURCE<CLASS<RUNTIME
一般如果需要在運行時去動態(tài)獲得注解的內(nèi)容阿宅,用RUNTIME注解
要在編譯時進行一些預處理工作,如ButterKnife,用CLASS注解笼蛛,注解會在class文件中存在洒放,但是在運行時會被丟棄。
做一些檢查性操作滨砍,如@override,用SOURCE注解源碼往湿,注解僅存在源碼級別,在編譯的時候丟棄該注解
1.首先創(chuàng)建一個Java工程存放注解 標注該注解作用域和生命周期惨好。
????@Target(ElementType.TYPE)
????@Retention(RetentionPolicy.CLASS)
????public @interface ARouter {
????????//詳細的路由路徑煌茴,必填 如"app/MainActivity"
????? ? Stringpath();
????? ? //從path中取出,規(guī)范開發(fā)者的編碼日川。
? ????? Stringgroup()default "";
????}
? ? 2.創(chuàng)建注解管理器蔓腐,主要作用是生成注解文件,返回當前使用注解的類
? ? ? ?(1) 在compiler中build.gradle中配置
????????//不可缺少龄句,注冊注解回论,并且生成文件
? ????? compileOnly'com.google.auto.service:auto-service:1.0-rc4'
? ????? annotationProcessor'com.google.auto.service:auto-service:1.0-rc4'
? ????? implementation project(':annotation')
????????//java控制臺亂碼
????? ? tasks.withType(JavaCompile){
????????options.encoding="utf-8"
????? ? }
????}
????//jdk編譯的版本是1.7
????sourceCompatibility ="7"
????targetCompatibility ="7"
? ? (2)通過重寫AbstractProcessor,獲得當前使用該注解的作用的名稱等信息分歇,并且動態(tài)
????????生成Library_Activity$$ARouter傀蓉,返回想要的屬性加載到內(nèi)存中,
@AutoService(Processor.class)//通過AutoService自動生成注解處理器
@SupportedAnnotationTypes({"com.example.annotation.ARouter"})
@SupportedSourceVersion(SourceVersion.RELEASE_7)
@SupportedOptions("content")
public class ARouterProcessorextends AbstractProcessor {
//操作Element工具類
? ? private ElementselementUtils;
? ? //type(類信息)工具類
? ? private TypestypeUtils;
? ? //用來輸出錯誤 警告等信息
? ? private Messagermessager;
? ? //文件生成器
? ? private Filerfiler;
? ? @Override
? ? public synchronized void init(ProcessingEnvironment processingEnvironment) {
super.init(processingEnvironment);
? ? ? ? elementUtils = processingEnvironment.getElementUtils();
? ? ? ? typeUtils = processingEnvironment.getTypeUtils();
? ? ? ? messager = processingEnvironment.getMessager();
? ? ? ? filer = processingEnvironment.getFiler();
? ? ? ? String content = processingEnvironment.getOptions().get("content");
? ? ? ? messager.printMessage(Diagnostic.Kind.NOTE, content);
? ? }
//可以用注解方式
//? ? @Override
//? ? public Set getSupportedAnnotationTypes() {
//? ? ? ? return super.getSupportedAnnotationTypes();
//? ? }
//? ? //必填
//? ? @Override
//? ? public SourceVersion getSupportedSourceVersion() {
//? ? ? ? return super.getSupportedSourceVersion();
//? ? }
//
//? ? @Override
//? ? public Set getSupportedOptions() {
//? ? ? ? return super.getSupportedOptions();
//? ? }
? ? /**
* 相當于main函數(shù)职抡,開始處理注解
* 注解處理器的核心方法葬燎,處理具體的注解,生成Java文件
*
? ? * @param set? ? ? ? ? ? ? 使用了支持處理的節(jié)點集合(類 上面寫了集合)
? ? * @param roundEnvironment 當前或是之前的運行環(huán)境缚甩,可以通過該對象查找找到該注解
? ? * @return true表示后續(xù)處理器不會再處理(已經(jīng)處理完成)
*/
? ? @Override
? ? public boolean process(Set set, RoundEnvironment roundEnvironment) {
if (set.isEmpty())return false;
? ? ? ? //獲取所有使用了Arouter注解的集合
? ? ? ? Set elements = roundEnvironment.getElementsAnnotatedWith(ARouter.class);
? ? ? ? for (Element element : elements) {
//類節(jié)點之上就是包節(jié)點
? ? ? ? ? ? String packageName =elementUtils.getPackageOf(element).getQualifiedName().toString();
? ? ? ? ? ? //獲取簡單類名
? ? ? ? ? ? String className = element.getSimpleName().toString();
? ? ? ? ? ? messager.printMessage(Diagnostic.Kind.NOTE, "被注解的類有:" + className);
? ? ? ? ? ? //最終我們想要生成的類文件
? ? ? ? ? ? String finalClassName = className +"$$ARouter";
? ? ? ? ? ? try {
JavaFileObject sourceFile =filer.createSourceFile(packageName +"." + finalClassName);
? ? ? ? ? ? ? ? Writer writer = sourceFile.openWriter();
? ? ? ? ? ? ? ? //設(shè)置包名
? ? ? ? ? ? ? ? writer.write("package " + packageName +";\n");
? ? ? ? ? ? ? ? writer.write("public class " + finalClassName +"{\n");
? ? ? ? ? ? ? ? writer.write("public static Class<?> findTargetClass(String path){\n");
? ? ? ? ? ? ? ? //獲取類之上ARouter注解的path值
? ? ? ? ? ? ? ? ARouter aRouter = element.getAnnotation(ARouter.class);
? ? ? ? ? ? ? ? writer.write("if(path.equalsIgnoreCase(\""+aRouter.path()+"\")){\n");
? ? ? ? ? ? ? ? writer.write("return "+className+".class;\n}\n");
? ? ? ? ? ? ? ? writer.write("return null;\n");
? ? ? ? ? ? ? ? writer.write("}\n}");
? ? ? ? ? ? ? ? //非常重要
? ? ? ? ? ? ? ? writer.close();
? ? ? ? ? ? }catch (IOException e) {
e.printStackTrace();
? ? ? ? ? ? }
}
return true;
? ? }
}
(3)在使用的包內(nèi)掃描注解處理器谱净,利用@SupportedOptions({"content"})將Java工程和application工程建立橋梁
//掃描注解處理器
annotationProcessor project(':compiler')
//在gradle中,配置選項參數(shù)值(只用于apt傳參)
//切記:必須寫在defaultConfig節(jié)點下
javaCompileOptions{
annotationProcessorOptions{
arguments=[content:'hello apt']
}
}
(4)在activity內(nèi)使用
//得到注解的信息
Class targeClass= Library_Activity$$ARouter.findTargetClass("/library/Library_Activity");
五 APT高級用法JavaPoet
什么事JavaPoet?
APT+JavaPoet=超級利刃
JavaPoet是square公司推出的開源Java代碼生成框架擅威,提供Java api生成.Java源文件壕探,這個框架功能非常實用,也是我們習慣的Java面向?qū)ο驩OP語法郊丛,可以很方便的使用它根據(jù)注解生成代碼李请,通過這種自動化生成代碼的方式瞧筛,可以讓我們更加簡潔優(yōu)雅的方式替換繁瑣冗雜的重復工作。
依賴JavaPoet
implementation' com.squareup:javapoet:1.9.0'
JavaPoet常用庫
? ? MethodSpec? ? ? ? ? ? 代表一個構(gòu)造函數(shù)或方法聲明
? ? TypeSpec? ? ? ? ? ? ? ? 代表一個類导盅、接口较幌、枚舉的聲明
? ? FieldSpec? ? ? ? ? ? ? ? 代表一個成員變量,一個字段的聲明
? ? JavaFile? ? ? ? ? ? ? ? ? ? 包含一個頂級類的Java文件
? ? ParameterSpec? ? ? ? 用來創(chuàng)建參數(shù)
? ? AnnotationSpec? ? ? ? 用來創(chuàng)建注解
? ? ClassName? ? ? ? ? ? ? ? 用來包裝一個類
? ? TypeName? ? ? ? ? ? ? ? ? 類型(如在添加返回值類型是使用TypeName.VOID)? ?
JavaPoet字符串格式化規(guī)則
$L????字面量????如"int value=$L",10
$S? ? 字符串????如 $S ,"hello"
$T? ? 接口?????????如?$T,MainActiivity
$N? ? 變量??????????如 user:$N,name
使用步驟同上面一摸一樣认轨,只是在AnnotationProcessor生成file的時候有所改變绅络,沒有那么多writer.write
//使用JavaPoet
ARouter aRouter=element.getAnnotation(ARouter.class);
MethodSpec methodSpec= MethodSpec.methodBuilder("findTargetClass")
.addModifiers(Modifier.PUBLIC,Modifier.STATIC)
.returns(Class.class)
.addParameter(String.class,"path")
.addStatement("return path.equals($S) ?$T.class : null",aRouter.path(), ClassName.get((TypeElement)element))
.build();
TypeSpec typeSpec=TypeSpec.classBuilder(finalClassName)
.addModifiers(Modifier.PUBLIC,Modifier.FINAL)
.addMethod(methodSpec)
.build();
JavaFile javaFile= JavaFile.builder(packageName,typeSpec).build();
try {
javaFile.writeTo(filer);
}catch (IOException e) {
e.printStackTrace();
}
六 路由架構(gòu)的設(shè)計
在組件化的架構(gòu)中,我們需要通過APT和JavaPoet技術(shù)生成什么樣的類文件呢嘁字?
為什么需要組名?
????避免程序一打開杉畜,所有信息全部加載進內(nèi)存纪蜒,節(jié)省內(nèi)存,提高性能
生成這些文件做什么用
? ? 通過組信息此叠,找到路徑文件記錄纯续,再在路徑文件記錄里面匹配,返回class信息灭袁。達到跳轉(zhuǎn)的目的猬错。