專案背景
先來說說開發此專案的背景,由於公司的專案採用元件化開發,各個元件內部需要在application中初始化一些特有的東西。通常的做法是在主專案中直接呼叫元件中的程式碼去完成初始化工作,這麼做是完全OK的;but現在有這麼一個設想,我能不能在編譯主專案時不去編譯某些元件,這樣做能極大的提高了主專案的編譯速度。下面我們來按照這個思路走一遍試試,首先要去掉某個元件就直接幹掉該元件在專案中的依賴就好了。當我們幹掉依賴時發現初始化該元件的地方報錯了,原因是找不到類檔案,仔細想一下就會發現我們這裡呼叫的是元件的類檔案,現在元件都被幹掉了,當然找不到這個類了。那該怎麼辦呢,我們直接註釋了吧,然後去跑專案完全ok。然後想要編譯該元件時再去手動開啟這個註釋,好累啊。。。那麼有沒有別的方案呢,我們的需求就想要去掉每個元件就直接去掉依賴就好了,為什麼還要去改動程式碼呢???? 答案是有辦法的,我們在初始化的時候其實只需要主專案的Application和當前編譯環境(debug/release),那我們就想辦法把這段初始化的程式碼自動生成,當我們依賴某個元件時自動去執行初始化的程式碼,不依賴時自然就不會去執行。就這樣Initer就應用而生了。
核心思想
使用編譯時註解自動生成初始化程式碼的代理類,統一呼叫
實現步驟
1、定義註解 @Inite
/**
* 初始化元件註解器
* Created by hezhiqiang on 2018/11/26.
*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.CLASS)
public @interface Inite {
}
複製程式碼
2、定義模板介面,這個類的作用是作為代理類的模板,所有生成的代理類都會實現此介面
/**
* 業務元件初始化模板
* Created by hezhiqiang on 2018/11/26.
*/
public interface IComponentInit {
void init(Context context, Boolean isDebug);
}
複製程式碼
3、在初始化工具類上增加註解
/**
* Created by hezhiqiang on 2018/12/3.
*/
@Inite
public class TestIniter1 {
public static void init(Context context, Boolean isDebug) {
Log.d("xxxTestIniter1","TestIniter1#init is be call");
}
}
複製程式碼
這裡需要注意兩點:
- init方法必須是用public static修飾
- 方法名和引數都是固定為init(Context context,boolean isDebug)
說明:由於初始化元件程式碼一般都是在Application中呼叫,目的只是為了得到應用的Application,因此我們這裡直接使用一個靜態的init方法將Application傳到元件即可。
4、使用註解生成器生成代理類,生成產物如下:
/**
* DO NOT EDIT THIS FILE!!! IT WAS GENERATED BY LCS_PROCESSOR. */
public class _InitImpl$$app implements IComponentInit {
@Override
public void init(Context context, Boolean isDebug) {
com.hzq.initer.TestIniter1.init(context,isDebug);
}
}
複製程式碼
5、提供初始化Api,作用是掃描生成的所有代理類,並呼叫初始化方法。
呼叫方式是如下:
/**
* Created by hezhiqiang on 2018/12/3.
*/
public class MyApplication extends Application {
@Override
public void onCreate() {
super.onCreate();
Initer.init(this,BuildConfig.DEBUG);
}
}
複製程式碼
總結
到此初始化外掛基本流程已經理清了,具體程式碼實現還請移駕到本人的github(qiangzi.github)檢視原始碼。
下面附上此外掛的使用方式
1、專案配置
在需要自動初始化的元件的build.gradle檔案中新增以下依賴:
android {
//......
defaultConfig {
//......
javaCompileOptions {
annotationProcessorOptions {
arguments = [moduleName: project.getName()]
}
}
}
//......
}
dependencies {
//......
implementation 'com.hzq.android:initer-api:1.0.1'
annotationProcessor 'com.hzq.android:initer-compiler:1.0.0'
}
複製程式碼
2、建立初始化元件工具類,並新增@Inite註解。注意這裡是靜態呼叫,所以init方法必須是static的
@Inite
public class TestIniter1 {
public static void init(Context context, Boolean isDebug) {
Log.d("xxxTestIniter1","TestIniter1#init is be call");
}
}
複製程式碼
3、在Application#onCreate中新增如下程式碼
Initer.init(this,BuildConfig.DEBUG);
複製程式碼