优雅地管理Android应用的初始化

前言

随着自己开发的应用的版本迭代,新功能不断增多,随之引入的第三方库也不可避免地多了起来,你可能就会发现自己应用Application中各种框架的初始化代码也在逐渐臃肿起来:什么推送啦,分享啦,统计啦,定位啦...另外还有你自己封装的一些工具和框架。这些七七八八加起来,可能最终你的Application可能会长这样:

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的整个生命周期,所以都会要求你在一开始的时候就进行初始化。

优化方案

对于单一模块的App来说,可能问题不大,只要先定义一个统一接口,然后分别实现,最后添加到一个集合,在Application中统一调用就好了:

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中统一调用这些初始化代码。

优雅地进行框架初始化

为了更好地解决这个问题,我写了Initiator这个Gradle插件。使用方法异常简单:在程序的任意位置,只要实现IAppInit接口就可以了,无需手动调用,Initiator会在编译时自动搜索所有实现了该接口的类,并生成调用init()方法的的代码。Initiator支持kotlin,支持Application类型和library类型的module。

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;//初始化执行延时时间,在主线程和工作线程都可以延时
}

采用编译期注解,不使用反射,代码在编译时生成,对最终程序运行性能影响很小。最终我们的代码可能如下:

@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文件中增加以下内容:

buildscript {

    repositories {
        google()
        jcenter()
        maven { url 'https://dl.bintray.com/renjianan/maven'}
    }
    dependencies {
         classpath 'com.renny.initiator:plugin:'${latest_version}"
    }
}
allprojects {
    repositories {
        google()
        jcenter()
        maven { url 'https://dl.bintray.com/renjianan/maven'}
    }
}

然后,在 applicationlibrary 模块的build.gradle 文件中应用插件:

apply plugin: 'com.android.application'
// apply plugin: 'com.android.library'
apply plugin: 'initiator'

Gradle Plugin或者实现方式感兴趣的同学请看源码:Github链接

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,425评论 4 361
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,058评论 1 291
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,186评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,848评论 0 204
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,249评论 3 286
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,554评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,830评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,536评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,239评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,505评论 2 244
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,004评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,346评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,999评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,060评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,821评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,574评论 2 271
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,480评论 2 267

推荐阅读更多精彩内容