1、简述
因为有在用dagger2,但是发现dagger2需要每次创建presenter的时候都要注入,感觉很繁琐,一直在想有没好的方法能解决这种问题
2、解决问题
使用apt自动生成presenter工厂类,首先我们创建一个apt module
添加如下引用
compile 'com.squareup:javapoet:1.8.0'
compile 'com.google.auto.service:auto-service:1.0-rc2'
2.1 APT的处理要素
注解处理器(AbstractProcess)+代码处理(javaPoet)+处理器注册(AutoService)+apt
@AutoService(Processor.class)
@SupportedAnnotationTypes("myapp.apt_lib.apt.InstanceFactory")
@SupportedSourceVersion(SourceVersion.RELEASE_8)
public class AnnotationProcess extends AbstractProcessor {
public Filer mFiler;
public Messager mMessager;
public Elements mElementUtils;
@Override
public boolean process(Set<? extends TypeElement> set, RoundEnvironment roundEnvironment) {
mFiler = processingEnv.getFiler();
mMessager = processingEnv.getMessager();
mElementUtils = processingEnv.getElementUtils();
new IntanceProcess().process(roundEnvironment, this);
return false;
}
}
//实现统一接口
public class IntanceProcess implements IProcess {
//类名
private static final String CLASS_NAME = "PresenterFactory";
//方法名
private static final String METHOD_NAME = "create";
@Override
public void process(RoundEnvironment roundEnv, AnnotationProcess process) {
TypeSpec.Builder tb = TypeSpec.classBuilder(CLASS_NAME)
.addJavadoc("@创建presenter工厂类")
.addModifiers(Modifier.PUBLIC, Modifier.FINAL);
MethodSpec.Builder method = MethodSpec.methodBuilder(METHOD_NAME)
.addAnnotation(MemoryCache.class)
.addModifiers(Modifier.PUBLIC, Modifier.STATIC)
.returns(Object.class)
.addParameter(Class.class, "clazz")
.addException(IllegalAccessException.class)
.addException(InstantiationException.class);
List<ClassName> list = new ArrayList<>();
CodeBlock.Builder cb = CodeBlock.builder();
cb.beginControlFlow("switch(clazz.getSimpleName())");
for (TypeElement typeElement : ElementFilter.typesIn(roundEnv.getElementsAnnotatedWith(InstanceFactory.class))) {
process.mMessager.printMessage(Diagnostic.Kind.NOTE, "正在创建" + typeElement.toString());
if (!Utils.isValidClass(process.mMessager, typeElement)) return;
ClassName className = ClassName.get(typeElement);
if (list.contains(className)) continue;
list.add(className);
cb.addStatement("case $S: return new $T()",typeElement.getSimpleName(),typeElement);
}
cb.addStatement("default: return clazz.newInstance()");
cb.endControlFlow();
method.addCode(cb.build());
tb.addMethod(method.build());
JavaFile javaFile = JavaFile.builder("myapp.apt.util",tb.build()).build();
try {
javaFile.writeTo(process.mFiler);
} catch (IOException e) {
e.printStackTrace();
}
}
}
2.2 Aop浅谈
2.2.1 oop
我们主要的代码都是oop 就是面向对象,OOP的精髓是把功能或问题模块化,每个模块处理自己的家务事,但是我们并不能做的很完美,所以就会出现各个模块互相入侵,如log打印等,各个模块都需要用到它,使得其他模块的代码和日志模块耦合非常紧密。
2.2.2 aop好处
AOP的目标是把这些功能集中起来,放到一个统一的地方来控制和管理。如果说,OOP如果是把问题划分到单个模块的话,那么AOP就是把涉及到众多模块的某一类问题进行统一管理。比如我们现在做的就是统一使用缓存,缓存所有的presenter,他会在编译期间织入我们的代码
/**
* 对presenter对象进行缓存切片
*/
@Aspect
public class MemoryCacheAspect {
private static final String POINTCUT_METHOD = "execution(myapp.apt_lib.aop.MemoryCache * *(..))";
@Pointcut(POINTCUT_METHOD)
public void methodMemoryCache() {
}
@Around("methodMemoryCache()")
public Object weaveJoinPoint(ProceedingJoinPoint joinPoint) throws Throwable {
CodeSignature signature = (CodeSignature) joinPoint.getSignature();
if (signature instanceof MethodSignature) {
String name = signature.getName();
MemoryCacheManager memoryCacheManager = MemoryCacheManager.getInstance();
StringBuffer sb = new StringBuffer();
sb.append(name);
//以方法名字和类名做Key
for (Object o : joinPoint.getArgs()) {
if (o instanceof Class) {
sb.append(((Class) o).getSimpleName());
}
}
String key = sb.toString();
Object result = memoryCacheManager.get(key);
if (result != null) {
return result;
}
//执行方法
result = joinPoint.proceed();
if (result != null) {
if (result instanceof Object) memoryCacheManager.put(key, result);
}
return result;
}
return null;
}
}
对presenter注解
@InstanceFactory
public class TextPresenter extends BasePresenter {
public TextPresenter(){}
public void text(String name){
Log.d(TextPresenter.class.getName(),name);
}
@Override
public void setView(BaseActivity view) {
}
}
- GitHub项目地址,欢迎fork或star,提出宝贵意见https://github.com/AndroidCrow/PresenterFactory