Load data ahead of time for Android
Activity/Fragment/View的初始化一般都会消耗一些时间,例如:
在打开页面Activity时,一般的流程是这样的:
上面的流程一般是串行的,即要等到Activity准备好后再去请求数据,而准备Activity的过程往往是耗时的过程(例如启动Activity涉及到跨进程、遍历创建View树都是耗时的过程),为什么不把这个过程改为并行的呢?甚至改为提前进行呢?
怎样优雅地把创建页面和请求数据并行进行,同时又不改变以前数据请求的调用方式呢?and-load-aot提供了一种思路:在需要加载数据的方法上添加注解标记,然后利用编译期注解生成页面与加载方法的映射关系,之后就可以在需要提前加载数据的时候调用该方法的路由去提前加载数据了
在项目的build.gradle中添加api依赖库以及编译时的注解处理器
annotationProcessor 'com.sw.aot.load
1.0.1'
implementation 'com.sw.aot.load
1.0.1'
implementation 'com.sw.aot.load
1.0.1'
添加注解处理器的配置信息AOT_INDEX,会在编译器生成该类ExampleAotIndex.java,该类里面含有加载方法的路由信息
defaultConfig {
javaCompileOptions {
annotationProcessorOptions {
arguments = [AOT_INDEX: 'com.sw.aot.example.ExampleAotIndex']
}
}
}
在加载数据的方法上加上@AOTLoad注解,注解的参数router代表着该方法的路由,后面会通过这个路由来调用该方法。加载数据的方法的返回值需要统一为ResultData
@AOTLoad(router = "/Example/LoadMockData")
public ResultData<String> loadMockData(){
ResultData<String> result = new ResultData<String>();
//load data from server or db ...
//mock load data asyn
new Thread(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(2000);
result.setCode(0);//加载成功
result.setData("MOCK: LOAD DATA SUCCESS");//设置数据
result.flush();//加载完毕
} catch (InterruptedException e) {
e.printStackTrace();
result.setCode(-1);//加载失败
result.flush();//加载完毕
}
}
}).start();
return result;
}
编译Build一下项目,就会生成含有上面注解信息的类ExampleAotIndex.java,例如:
```java
/* This class is generated by AOTLoad, do not edit. /
public class ExampleAotIndex implements AotRouterInterface{
/ mock load async data /
public static String EXAMPLE_LOADMOCKDATA = “/Example/LoadMockData”;
private final HashMap
private final HashMap
public ExampleAotIndex() {
routerMethodMap.put(EXAMPLE_LOADMOCKDATA, "loadMockData");
routerClassMap.put(EXAMPLE_LOADMOCKDATA, com.sw.aot.example.ExampleActivity.class );
}
@Override
public HashMap
return routerMethodMap;
}
@Override
public HashMap
return routerClassMap;
}
}
- 在应用启动后注入路由表ExampleAotIndex,一般在Application中:
```java
AotLoader.enableLog(true);//是否开始日志
AotLoader.addRouter(new ExampleAotIndex());//注入加载方法的路由表
Debug模式下可以开启日志,开启了以后可以查看任务链的日志信息:
adb logcat -s AOT_LOG
现在就可以根据方法路由来提前执行加载任务的方法了,该框架将加载数据的方法抽象为生产和消费的task,是一个典型的生产者消费者模型。
当打开Activity前去生产加载数据的task,执行AotLoader.produce(methodRouter),会根据传人的方法路由名来定位到申明了该注解路由的方法,然后反射调用执行,AotLoader.produce
(methodRouter)的返回值是该任务的ID,将ID以参数的形式传给Activity
public static void invoke(Context context){
Intent intent = new Intent(context, ExampleActivity.class);
intent.putExtra(START_AOT_LOAD_ID, AotLoader.produce(ExampleAotIndex.EXAMPLE_LOADMOCKDATA));
context.startActivity(intent);
}
Activity初始化完成并且View准备好以后,就可以根据传递过来的任务的ID来消费提前加载的数据了:
aotTaskId = getIntent().getStringExtra(START_AOT_LOAD_ID);
if(AotLoader.isValidTask(aotTaskId)){
AotLoader.consume(aotTaskId, listener);
}
通过上面的回调就可以收到数据更新了,一旦调用了ResultData