隨着本身開發的應用的版本迭代,新功能不斷增多,隨之引入的第三方庫也不可避免地多了起來,你可能就會發現本身應用Application
中各類框架的初始化代碼也在逐漸臃腫起來:什麼推送啦,分享啦,統計啦,定位啦...另外還有你本身封裝的一些工具和框架。這些七七八八加起來,可能最終你的Application
會變成這樣:java
public class App extends Application {
@Override
public void onCreate() {
super.onCreate();
//初始化推送
PushAgent mPushAgent = PushAgent.getInstance(this);
mPushAgent.register(new IUmengRegisterCallback() {
@Override
public void onSuccess(String deviceToken) {
//註冊成功會返回device token
}
@Override
public void onFailure(String s, String s1) {
}
});
//初始化統計
UMConfigure.init(this,"5a12384aa40fa3551f0001d1","umeng",UMConfigure.DEVICE_TYPE_PHONE,"");
//初始化分享
PlatformConfig.setWeixin("wxdc1e388c3822c80b", "3baf1193c85774b3fd9d18447d76cab0");
PlatformConfig.setSinaWeibo("3921700954", "04b48b094faeb16683c32669824ebdad","http://sns.whalecloud.com");
PlatformConfig.setYixin("yxc0614e80c9304c11b0391514d09f13bf");
PlatformConfig.setQQZone("100424468", "c7394704798a158208a74ab60104f0ba");
PlatformConfig.setTwitter("3aIN7fuF685MuZ7jtXkQxalyi", "MK6FEYG63eWcpDFgRYw4w9puJhzDl0tyuqWjZ3M7XJuuG7mMbO");
//初始化定位
LocationClient mLocationClient = new LocationClient(context);
mLocationClient.setLocOption(getLocationOption());
mLocationClient.registerLocationListener(new MyLocationListener());
mLocationClient.start();
mLocationClient.requestLocation();
//初始化glide
DisplayOption options = DisplayOption.builder().setDefaultResId(R.drawable.ic_default)
.setErrorResId(-1).setLoadingResId(-1);
imageDisplayLoader.setDefaultDisplayOption(options);
//初始化本身的一些工具
registerActivityLifecycleCallbacks(new ActivityLifecycleCallbacks() {
@Override
public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
}
});
}
}
複製代碼
上面我只是列舉了一些經常使用的功能框架,從我的開發經驗上說,這些應用程序級別的框架,做用的時間貫穿APP的整個生命週期,因此都會要求你在一開始的時候就進行初始化。android
優化方案git
對於單一模塊的App來講,可能問題不大,只要先定義一個統一接口,而後分別實現,最後添加到一個集合,在Application
中統一調用就行了:github
public interface IAppInit {
void init(@NonNull Application application);
}
public class App extends Application {
@Override
public void onCreate() {
super.onCreate();
List<IAppInit> initList = new ArrayList<>();
initList.add(new ShareInit());
initList.add(new PushInit());
initList.add(new ImageInit());
for (IAppInit iAppInit : initList) {
iAppInit.init(this);
}
}
}
複製代碼
但現在不少的進行了組件化的改造,其中的一個重要思想就是功能模塊的組件化,也就是解耦,彼此互不依賴,但若是咱們仍是像上面這樣作的話就等於違背了這個思想,把這些功能模塊的初始化代碼所有集中在了一塊兒。更好的方案固然是在模塊內部作初始化,並且不須要在Application中統一調用這些初始化代碼。bash
爲了更好地解決這個問題,我寫了Initiator這個Gradle插件。使用方法異常簡單:在程序的任意位置,只要實現IAppInit
接口就能夠了,無需手動調用,Initiator會在編譯時自動搜索全部實現了該接口的類,並生成調用init()
方法的的代碼。Initiator支持kotlin,支持Application類型和library類型的module。app
public class PushInit implements IAppInit {
@Override
public void init(Application application) {
Log.d("init==", "PushInit");
}
}
複製代碼
爲了知足更多初始化需求,還能夠爲每一個初始化增長多種配置,只要在這個類上加一個@AppInit
註解就好了:框架
@Retention(RetentionPolicy.CLASS)
@Target({ElementType.TYPE})
public @interface AppInit {
boolean background() default false; //在工做線程中初始化,默認false
boolean inChildProcess() default true;//容許在子進程中初始化,多進程應用Application的onCreate方法會調用屢次,默認true
boolean onlyInDebug() default false;//只在debug中作初始化,默認false
int priority() default 0;//初始化優先級,數字越大,優先級越高,初始化時間越早
long delay() default 0L;//初始化執行延時時間,在主線程和工做線程均可以延時
}
複製代碼
採用編譯期註解,不使用反射,代碼在編譯時生成,對最終程序運行性能影響很小。最終咱們的代碼可能以下:ide
@AppInit(priority = 22, delay = 1740, onlyInDebug = true)
public class PushInit implements IAppInit {
@Override
public void init(Application application) {
Log.d("init==", "PushInit");
}
}
複製代碼
注意,若是你沒有作這些特別的配置,不須要加這個註解。另外你可能對Application
作了多重繼承Initiator會找到多個Application的子類,請在你須要初始化的入口加上@InitContext
註解:工具
@InitContext
public class App extends BaseApplication {
}
複製代碼
目前暫時只支持Application
類型,後期考慮增長Activity
的支持,由於有些初始化能夠延後放到啓動頁或首頁來作。目前能夠用延時策略替代。組件化
首先,在項目根目錄的 build.gradle
文件中增長如下內容:
dependencies {
classpath 'com.renny.initiator:plugin:'${latest_version}" } 複製代碼
而後,在 application
或 library
模塊的build.gradle
文件中應用插件:
apply plugin: 'com.android.application'
// apply plugin: 'com.android.library'
apply plugin: 'initiator'
複製代碼
對Gradle Plugin
或者實現方式感興趣的同窗請看源碼:Github連接。歡迎你們找找bug,提提新功能~