社区微信群开通啦,扫一扫抢先加入社区官方微信群
社区微信群
每个Android应用启动时,都会先创建一个Application。通常在Application里我们会做一些应用初始化的操作,常见的有第三方SDK初始化。在应用组件化之后,组件与壳工程是隔离开来的,但是组件有时候也需要获取应用的Application,也需要在应用启动时进行初始化。这就涉及到组件的生命周期管理问题。
最简单的实现方式如下:
public interface IAppLike {
void onCreate();
void onTerminate();
void onLowMemory();
void onTrimMemory(int level);
}
public class NewsDelegate implements IApplicationDelegate {
@Override
public void onCreate() {
Log.i("hx", "NewsDelegate-onCreate");
}
@Override
public void onTerminate() {
Log.i("hx", "NewsDelegate-onTerminate");
}
@Override
public void onLowMemory() {
}
@Override
public void onTrimMemory(int level) {
}
}
@Override
public void onCreate() {
super.onCreate();
MainDelegate mainDelegate = new MainDelegate();
NewsDelegate newsDelegate = new NewsDelegate();
MusicDelegate musicDelegate = new MusicDelegate();
MimeDelegate mimeDelegate = new MimeDelegate();
mainDelegate.onCreate();
newsDelegate.onCreate();
musicDelegate.onCreate();
mimeDelegate.onCreate();
}
看起来貌似很简单,根本没什么技术含量,但是实际运用时,你会发现很多问题:
(1)组件初始化先后顺序问题:
前面介绍过,上层业务组件是依赖下层业务组件的,如果下层组件在应用启动时也需要初始化,那么我们在加载组件时,必然要先加载下层组件,否则加载上层组件时可能会出现问题。但是组件这么多,我们怎么确定要先加载谁后加载谁呢,当然你可以手动维护,代码里写死,但是当业务越来越多、时间越来越久,肯定不灵活,你新加一个业务组件进来,你都需要确定组件初始化先后顺序。所以,我们必须有个机制来确定组件初始化先后顺序。
类似线程优先级一样, 为每个组件定义了一个优先级,通过重写getPriority()方法可以设置组件的优先级。优先级范围从[1-10],默认优先级都为5,下层组件或需要先初始化的组件,优先级设置高一点。这样我们在加载组件的时候,先对所有组件的优先级进行排序,优先级高的排前面,然后再按顺序进行加载组件,就可解决这个问题了。
(2)自动加载问题
这里需要在壳工程代码里,手动构建各个组件的Delegate类。如果很多个组件都有实现该类,那在集成时得一个一个找出这些类,并且新增加一个组件,你都有可能要去修改壳工程代码,这样显然是不灵活且不利于代码维护的。如果能自动读取并加载这些Delegate类,那显然是极好的,这里有2种方式来实现:
应用启动时通过包名全局扫描源代码文件并找到代理类,通过反射去加载并初始化组件。这种方式只需要在组件中实现代理类即可,实现起来比较简单,但是全局扫描有性能的损耗。
通过自定义gradle插件和字节码插入技术来实现AOP,在编译期间在BaseApplication生命周期中动态注入字节码,实现调用代理类的对应方法。
在BaseApplication初始化时扫描出所有组件的代理类,再通过反射加载并初始化。这里也有个问题,所有组件的代理类散落在各个不同的组件中,包名各不相同,当扫描到class文件后判断条件就必须是【class文件全类命.equal(组件1代理类全类命) || class文件全类命.equal(组件2代理类全类命) || …】,是不是很麻烦,这里我们可以采取apt技术,通过编译时注解动态生成这些代理类的辅助文件,在辅助文件中调用代理类的方法,而这些辅助文件的包名一样,这样我们只需要扫描辅助文件就可以了,判断条件就变成【class文件包名.startWith(辅助文件包名)】,是不是简单多了。
初步思路:
初步技术难点:
需要了解APT技术,怎么在编译时动态生成java代码;关于编译时注解可以参考详解Android注解 Annotation这篇文章。
应用在运行时,怎么能扫描到某个包名下有多少个class,以及他们的名称呢;
在Android Studio中,新建一个Java Library module,命名为lifecycle-annotation,在该module中创建一个注解类,同时创建一个后面要生成代理类的相关配置文件。
注解类:
@Retention(RetentionPolicy.CLASS)
@Target(ElementType.TYPE)
public @interface AppLifeCycle { }
配置文件:
public class LifeCycleConfig {
/*** 生成代理类的包名 */
public static final String PROXY_CLASS_PACKAGE_NAME = "com.example.lifecycle.apt.proxy";
/*** 生成代理类统一的后缀 */
public static final String PROXY_CLASS_SUFFIX = "$$Proxy";
/*** 生成代理类统一的前缀 */
public static final String PROXY_CLASS_PREFIX = "Watson$$"; }
新建一个Java Library module,命名为lifecycle-apt,在该module里实现我们自己的注解处理器。
在build.gradle里修改配置为:
apply plugin: 'java-library'
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'com.google.auto.service:auto-service:1.0-rc2'
implementation project(':lifecycle-annotation')
}
sourceCompatibility = "1.8"
targetCompatibility = "1.8"
tasks.withType(JavaCompile) {
options.encoding = "UTF-8"
}
接下来就是实现我们自己的注解处理器了:
@AutoService(Processor.class)
public class AppLikeProcessor extends AbstractProcessor {
private Elements mElementUtils;
private Map<String, AppLikeProxyClassCreator> mMap = new HashMap<>();
@Override
public synchronized void init(ProcessingEnvironment processingEnvironment) {
super.init(processingEnvironment);
mElementUtils = processingEnvironment.getElementUtils();
}
/*** 支持解析的注解 */
@Override
public Set<String> getSupportedAnnotationTypes() {
Set<String> set = new LinkedHashSet<>();
set.add(AppLifeCycle.class.getCanonicalName());
return set;
}
@Override
public SourceVersion getSupportedSourceVersion() {
return SourceVersion.RELEASE_8;
}
@Override
public boolean process(Set<? extends TypeElement> set, RoundEnvironment roundEnvironment) {
Set<? extends Element> elements = roundEnvironment.getElementsAnnotatedWith(AppLifeCycle.class);
mMap.clear();
for (Element element : elements) {
if (!element.getKind().isClass()) {
throw new RuntimeException("Annotation AppLifeCycle can only be used in class.");
}
TypeElement typeElement = (TypeElement) element;
//这里检查一下,使用了该注解的类,同时必须要实现com.example.lifecycle.api.IAppLike接口,否则会报错,因为我们要实现一个代理类
List<? extends TypeMirror> mirrorList = typeElement.getInterfaces();
if (mirrorList.isEmpty()) {
throw new RuntimeException(typeElement.getQualifiedName() + " must implements interface com.example.lifecycle.api.IAppLike");
}
boolean checkInterfaceFlag = false;
for (TypeMirror mirror : mirrorList) {
if ("com.example.lifecycle.api.IAppLike".equals(mirror.toString())) {
checkInterfaceFlag = true;
}
}
if (!checkInterfaceFlag) {
throw new RuntimeException(typeElement.getQualifiedName() + " must implements interface com.example.lifecycle.api.IAppLike");
}
String fullClassName = typeElement.getQualifiedName().toString();
if (!mMap.containsKey(fullClassName)) {
System.out.println("process class name : " + fullClassName);
AppLikeProxyClassCreator creator = new AppLikeProxyClassCreator(mElementUtils, typeElement);
mMap.put(fullClassName, creator);
}
}
System.out.println("start to generate proxy class code");
for (Map.Entry<String, AppLikeProxyClassCreator> entry : mMap.entrySet()) {
String className = entry.getKey();
AppLikeProxyClassCreator creator = entry.getValue();
System.out.println("generate proxy class for " + className);
try {
JavaFileObject jfo = processingEnv.getFiler().createSourceFile(creator.getProxyClassFullName());
Writer writer = jfo.openWriter();
writer.write(creator.generateJavaCode());
writer.flush();
writer.close();
} catch (Exception e) {
e.printStackTrace();
}
}
return true;
}
}
public class AppLikeProxyClassCreator {
private Elements mElementUtils;
private TypeElement mTypeElement;
private String mProxyClassSimpleName;
public AppLikeProxyClassCreator(Elements elements, TypeElement typeElement) {
mElementUtils = elements;
mTypeElement = typeElement;
mProxyClassSimpleName = LifeCycleConfig.PROXY_CLASS_PREFIX + mTypeElement.getSimpleName().toString() + LifeCycleConfig.PROXY_CLASS_SUFFIX;
}
/**
* 获取要生成的代理类的完整类名 * * @return
*/
public String getProxyClassFullName() {
String name = LifeCycleConfig.PROXY_CLASS_PACKAGE_NAME + "." + mProxyClassSimpleName;
return name;
}
/**
* 生成java代码
*/
public String generateJavaCode() {
StringBuilder sb = new StringBuilder();
//设置包名
sb.append("package ").append(LifeCycleConfig.PROXY_CLASS_PACKAGE_NAME).append(";nn");
//设置import部分
sb.append("import android.content.Context;n");
sb.append("import com.example.lifecycle.api.IAppLike;n");
sb.append("import ").append(mTypeElement.getQualifiedName()).append(";nn");
sb.append("public class ").append(mProxyClassSimpleName).append(" implements ").append("IAppLike ").append(" {nn");
//设置变量
sb.append(" private ").append(mTypeElement.getSimpleName().toString()).append(" mAppLike;nn");
//构造函数
sb.append(" public ").append(mProxyClassSimpleName).append("() {n");
sb.append(" mAppLike = new ").append(mTypeElement.getSimpleName().toString()).append("();n");
sb.append(" }nn");
//getPriority()方法
sb.append(" public int getPriority() {n");
sb.append(" return mAppLike.getPriority();n");
sb.append(" }nn");
//onCreate()方法
sb.append(" public void onCreate() {n");
sb.append(" mAppLike.onCreate();n");
sb.append(" }nn");
//onTerminate方法
sb.append(" public void onTerminate() {n");
sb.append(" mAppLike.onTerminate();n");
sb.append(" }nn");
//onTerminate方法
sb.append(" public void onLowMemory() {n");
sb.append(" mAppLike.onLowMemory();n");
sb.append(" }nn");
//onTerminate方法
sb.append(" public void onTrimMemory(int level) {n");
sb.append(" mAppLike.onTrimMemory(level);n");
sb.append(" }nn");
sb.append("n}");
return sb.toString();
}
}
关于APT的调试可以参考https://blog.csdn.net/zhangteng22/article/details/54946270这篇文章。
在前面定义的几个组件代理类上添加注解@AppLifeCycle
//实现了IAppLike接口,并且采用了AppLifeCycle注解,二者缺一不可,否则APT处理时会报错
@AppLifeCycle
public class MainDelegate implements IAppLike {
@Override
public int getPriority() {
return 10;
}
@Override
public void onCreate() {
Log.i("hx", "MainDelegate-onCreate");
}
@Override
public void onTerminate() {
Log.i("hx", "MainDelegate-onTerminate");
}
@Override
public void onLowMemory() {
}
@Override
public void onTrimMemory(int level) {
}
}
同时修改组件的build.gradle,添加依赖:
//---------其他依赖------------
api project(':lifecycle-annotation')
api project(':lifecycle-api')
//需要注意这里是使用 annotationProcessor,即我们刚定义的注解处理器
annotationProcessor project(':lifecycle-apt')
到这里注解处理器就可以工作啦,将整个工程编译一下,可以看到在build目录下已经生成了我们定义的注解类,具体路径如下所示:
打开看一下呢:
public class Watson$$MainDelegate$$Proxy implements IAppLike {
private MainDelegate mAppLike;
public Watson$$MainDelegate$$Proxy() {
mAppLike = new MainDelegate();
}
public int getPriority() {
return mAppLike.getPriority();
}
public void onCreate() {
mAppLike.onCreate();
}
public void onTerminate() {
mAppLike.onTerminate();
}
public void onLowMemory() {
mAppLike.onLowMemory();
}
public void onTrimMemory(int level) {
mAppLike.onTrimMemory(level);
}
}
新建一个Android Library module,命名为lifecycle-api,在这个module里定义IAppLike接口,以及一个生命周期管理类。现在工程目录差不多是这样的:
public interface IAppLike {
int MAX_PRIORITY = 10;
int MIN_PRIORITY = 1;
int NORM_PRIORITY = 5;
default int getPriority() {
return NORM_PRIORITY;
}
void onCreate();
void onTerminate();
void onLowMemory();
void onTrimMemory(int level);
}
生命周期管理类,初始化的时候扫描所有的代理辅助类,并在相应方法中调用组件生命周期方法。
public class AppLifeCycleManager {
/**
* 初始化
*/
public static void init(Context context) {
scanClassFile(context);
Log.d("hx", "代理子模块数目:" + APP_LIKE_LIST.size());
Collections.sort(APP_LIKE_LIST, new AppDelegateComparator()); //优先级排序
}
public static void onCreate() {
for (IAppLike delegate : APP_LIKE_LIST) {
delegate.onCreate();
}
}
public static void onTerminate() {
for (IAppLike delegate : APP_LIKE_LIST) {
delegate.onTerminate();
}
}
public static void onLowMemory() {
for (IAppLike delegate : APP_LIKE_LIST) {
delegate.onLowMemory();
}
}
public static void onTrimMemory(int level) {
for (IAppLike delegate : APP_LIKE_LIST) {
delegate.onTrimMemory(level);
}
}
/**
* 扫描出固定包名下,实现了
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!