1、簡(jiǎn)述
因?yàn)橛性谟胐agger2,但是發(fā)現(xiàn)dagger2需要每次創(chuàng)建presenter的時(shí)候都要注入,感覺(jué)很繁瑣,一直在想有沒(méi)好的方法能解決這種問(wèn)題
2、解決問(wèn)題
使用apt自動(dòng)生成presenter工廠類,首先我們創(chuàng)建一個(gè)apt module
添加如下引用
compile 'com.squareup:javapoet:1.8.0'
compile 'com.google.auto.service:auto-service:1.0-rc2'
2.1 APT的處理要素
注解處理器(AbstractProcess)+代碼處理(javaPoet)+處理器注冊(cè)(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;
}
}
//實(shí)現(xiàn)統(tǒng)一接口
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("@創(chuàng)建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, "正在創(chuàng)建" + 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 就是面向?qū)ο?,OOP的精髓是把功能或問(wèn)題模塊化,每個(gè)模塊處理自己的家務(wù)事,但是我們并不能做的很完美,所以就會(huì)出現(xiàn)各個(gè)模塊互相入侵,如log打印等,各個(gè)模塊都需要用到它,使得其他模塊的代碼和日志模塊耦合非常緊密。
2.2.2 aop好處
AOP的目標(biāo)是把這些功能集中起來(lái),放到一個(gè)統(tǒng)一的地方來(lái)控制和管理。如果說(shuō),OOP如果是把問(wèn)題劃分到單個(gè)模塊的話,那么AOP就是把涉及到眾多模塊的某一類問(wèn)題進(jìn)行統(tǒng)一管理。比如我們現(xiàn)在做的就是統(tǒng)一使用緩存,緩存所有的presenter,他會(huì)在編譯期間織入我們的代碼
/**
* 對(duì)presenter對(duì)象進(jìn)行緩存切片
*/
@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;
}
//執(zhí)行方法
result = joinPoint.proceed();
if (result != null) {
if (result instanceof Object) memoryCacheManager.put(key, result);
}
return result;
}
return null;
}
}
對(duì)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項(xiàng)目地址,歡迎fork或star,提出寶貴意見(jiàn)https://github.com/AndroidCrow/PresenterFactory