现在很多开源框架使用注解来解耦,但是利用反射来使用注解的方式很耗费性能,随着annotationProcessor和android-apt的出现通过注解根据反射机制动态编译生成代码的方式来解决在运行时不再使用发射机制,下面我们试着利用annotationProcessor和android-apt来替换反射的方式。
public static Map<String, BasePresenter> createPresenters(BaseMethodCenter methodCenter, Class<?> clazz) {
Map<String, BasePresenter> map = new HashMap<>();
try {
Annotation[] classAnnotations = clazz.getAnnotations();
for(Annotation annotation : classAnnotations){
if(annotation instanceof Presenter){
String[] classes = ((Presenter) annotation).value();
for(String className:classes){
Class presenterClass = Class.forName(MethodCenter.getPresenterPath()+"."+className);
Constructor<BasePresenter> constructor = presenterClass.getConstructor(BaseMethodCenter.class);
constructor.setAccessible(true);
BasePresenter presenter = constructor.newInstance(methodCenter);
map.put(className, presenter);
BaseLog.d(""+className+" added");
}
}
}
} catch (NoSuchMethodException e) {
e.printStackTrace();
BaseLog.e("createPresenters NoSuchMethodException");
} catch (ClassNotFoundException e) {
e.printStackTrace();
BaseLog.e("createPresenters ClassNotFoundException");
} catch (InvocationTargetException e) {
e.printStackTrace();
BaseLog.e("createPresenters InvocationTargetException");
} catch (IllegalAccessException e) {
e.printStackTrace();
BaseLog.e("createPresenters IllegalAccessException");
} catch (InstantiationException e) {
e.printStackTrace();
BaseLog.e("createPresenters InstantiationException");
}
return map;
}
这个方法通过反射生成BasePresenter
@Presenter(value = {TestPresenter.class})
public class ViewMethodCenter extends MethodCenter {
ViewMethodCenter通过注解@Presenter生成TestPresenter实例,并将其保存在Map中,
这个是原先的设计,presenter实例创建采用了注解和反射,而model对象创建更容易出错
1.性能比直接调用要差,一个presenter实例看不出来,随着presenter的增多,性能的差距就开始显现
public abstract class BasePresenter<Model extends IContract.IModel>{
Model mModel = createModel();
......
public abstract Model createModel();
......
}
2.model在presenter的子类中生成,必须复写createModel抽象方法
利用annotationProcessor,首先创建一个java lib 的module,暂命名为apt
@AutoService(Processor.class)//自动生成 javax.annotation.processing.IProcessor 文件
@SupportedSourceVersion(SourceVersion.RELEASE_7)//java版本支持
@SupportedAnnotationTypes({//标注注解处理器支持的注解类型
"com.pluginmvpm.annotation.InstanceFactory"
})
public class AnnotationProcessor extends AbstractProcessor {
public Filer mFiler; //文件相关的辅助类
public Elements mElements; //元素相关的辅助类
public Messager mMessager; //日志相关的辅助类
@Override
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
mFiler = processingEnv.getFiler();
mElements = processingEnv.getElementUtils();
mMessager = processingEnv.getMessager();
new InstanceProcessor().process(roundEnv, this);
return true;
}
}
创建AnnotationProcessor,
public class InstanceProcessor implements IProcessor {
@Override
public void process(RoundEnvironment roundEnv, AnnotationProcessor mAbstractProcessor) {
String CLASS_NAME = "InstanceFactory";
TypeSpec.Builder tb = classBuilder(CLASS_NAME).addModifiers(PUBLIC, FINAL).addJavadoc("@ 实例化工厂 此类由apt自动生成");
MethodSpec.Builder methodBuilder1 = MethodSpec.methodBuilder("create").addAnnotation(MemoryCache.class)
.addJavadoc("@此方法由apt自动生成")
.returns(Object.class).addModifiers(PUBLIC, STATIC).addException(IllegalAccessException.class).addException(InstantiationException.class)
.addParameter(Class.class, "mClass");
List<ClassName> mList = new ArrayList<>();
CodeBlock.Builder blockBuilder = CodeBlock.builder();
blockBuilder.beginControlFlow(" switch (mClass.getSimpleName())");//括号开始
try {
for (TypeElement element : ElementFilter.typesIn(roundEnv.getElementsAnnotatedWith(InstanceFactory.class))) {
mAbstractProcessor.mMessager.printMessage(Diagnostic.Kind.NOTE, "正在处理: " + element.toString());
if (!Utils.isValidClass(mAbstractProcessor.mMessager, element)) return;
ClassName currentType = ClassName.get(element);
if (mList.contains(currentType)) continue;
mList.add(currentType);
blockBuilder.addStatement("case $S: return new $T()", currentType.simpleName(), currentType);//初始化Presenter
}
blockBuilder.addStatement("default: return mClass.newInstance()");
blockBuilder.endControlFlow();
methodBuilder1.addCode(blockBuilder.build());
tb.addMethod(methodBuilder1.build());
JavaFile javaFile = JavaFile.builder(Utils.PackageName, tb.build()).build();// 生成源代码
javaFile.writeTo(mAbstractProcessor.mFiler);// 在 app module/build/generated/source/apt 生成一份源代码
} catch (FilerException e) {
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
}
InstanceProcessor主要用来生成Java代码,
public final class InstanceFactory {
/**
* @此方法由apt自动生成 */
public static Object create(Class mClass) throws IllegalAccessException, InstantiationException {
switch (mClass.getSimpleName()) {
case "TestPresenter": return new TestPresenter();
default: return mClass.newInstance();
}
}
}
所有包含@InstanceFactory注解的类都会自动生成,例如TestPresenter
dependencies {
compile fileTree(include: ['*.jar'], dir: 'libs')
androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
exclude group: 'com.android.support', module: 'support-annotations'
})
compile 'com.android.support:appcompat-v7:25.2.0'
testCompile 'junit:junit:4.12'
compile project(':lib')
annotationProcessor project(':apt')
}
在gradle中关联apt工程,会自动编译生成InstanceFactory类
public class InstanceUtil {
/**
* 通过实例工厂去实例化相应类
*
* @param <T> 返回实例的泛型类型
* @return
*/
@TimeLog
public static <T> T getInstance(Class clazz) {
try {
return (T) InstanceFactory.create(clazz);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
封装成util使用
protected void initPresenter() {
mPresenterMap = new HashMap<>();
Annotation[] annotations = getClass().getAnnotations();
for (Annotation annotation:annotations){
if(annotation instanceof Presenter){
Class[] presenters = ((Presenter) annotation).value();
for(Class presenter : presenters){
InstanceUtil.getInstance(presenter);
BaseLog.d("presenter "+presenter.getName()+" added!");
}
}
}
}
改造后的代码,利用InstanceUtil创建presenter实例,解决了第一个问题
public BasePresenter(){
if (this.getClass().getGenericSuperclass() instanceof ParameterizedType &&
((ParameterizedType) (this.getClass().getGenericSuperclass())).getActualTypeArguments().length > 0) {
Class modelClass = (Class) ((ParameterizedType) (this.getClass()
.getGenericSuperclass())).getActualTypeArguments()[0];
model = InstanceUtil.getInstance(modelClass);
}
this.mMethodCenter = MethodCenter.getInstance();
init();
}
InstanceUtil还可以创建其他无参实例,拿到Presenter的泛型,直接创建出model,省去了model创建的部分,解决了第二个问题
总之,利用annotationProcessor生成的Java文件InstanceFactory类配合注解和泛型完美解决了MVP各层对象生成的问题
项目地址
https://github.com/jasonwang18/pluginMVPM
本文参考了T-MVP项目north大神的实例创建和分层的思想
https://github.com/north2016/T-MVP