and-load-aot

Project address: AND-load-aOT

  • Before opening the page, call the method that loads the data (maybe network data or database) so that the data is ready to be displayed to the user immediately after opening the page. Page initialization usually takes time. In this way, the initialization time can be saved. The page is initialized and the data is loaded in parallel, shortening the total time displayed to users.
  • Here’s an example: For example, when the Activity on page A is started and the startActivity method is called, loadData() of page A is called. At this time, network data starts to be loaded and Acitivity starts to initialize the loading layout. When the Activity is ready and the UI needs data, check whether loadData() is finished. If it is, the data is displayed directly. If it is not, loading is displayed and wait for it to complete.

About

Initialization of an Activity/Fragment/View usually takes some time, for example:

  • When a page Activity is started, the general flow looks like this:

    • 1. Notify the AMS process to create a new Activity
    • 2. AMS checks whether the Activity process exists. If the process does not exist, it will first create an Activity instance
    • 3. Load the layout View after the Activity is created
    • 4, then go to the network or database asynchronously request data
    • 5. Notify rendering to View when data is ready
  • The above process is usually serial, waiting until the Activity is ready to request data, and preparing the Activity is often a time-consuming process (for example, starting the Activity involves cross-process, traversing and creating a View tree are time-consuming processes). Why not make this process parallel? Or even earlier?

  • How can you elegantly create pages and request data in parallel without changing how previous data requests were invoked? And-load-aot provides the idea of adding annotation tags to methods that need to load data, then using compile-time annotations to generate a mapping between the page and the load method, and then calling the route of that method to preload data when it needs to be preloaded

Usage

Detailed see ExampleActivity

  • Add apI-dependent libraries and compile-time annotation handlers to your project’s build.gradle
    annotationProcessor 'com. Sw. Aot. The load, the load - - aot compiler: 1.0.1'
    implementation 'com. Sw. Aot. The load, the load - aot - the annotation: 1.0.1'
    implementation 'com. Sw. Aot. The load, the load - aot - API: 1.0.1'
Copy the code
  • Adding the configuration information for the annotation handler, AOT_INDEX, generates the exampleAotIndex.java class in the compiler that contains the route information for the loading method
defaultConfig {
    javaCompileOptions {
        annotationProcessorOptions {
             arguments = [AOT_INDEX: 'com.sw.aot.example.ExampleAotIndex']}}}Copy the code
  • Add the @aotLoad annotation to the method that loads the data. The annotation’s router parameter represents the route to the method from which the method will be called.
    @AOTLoad(router = "/Example/LoadMockData")
    public ResultData<String> loadMockData(a){
        final ResultData<String> result = new ResultData<String>();
        new Thread(new Runnable() {
            @Override
            public void run(a) {
                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;
    }
Copy the code
  • Compile and Build the project to generate the class exampleAotIndex.java with the above annotation information, for example:
/** 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<String, String> routerMethodMap = new HashMap<String, String>();
    private finalHashMap<String, Class<? >> routerClassMap =newHashMap<String, Class<? > > ();public ExampleAotIndex(a) {
         routerMethodMap.put(EXAMPLE_LOADMOCKDATA, "loadMockData");
         routerClassMap.put(EXAMPLE_LOADMOCKDATA, com.sw.aot.example.ExampleActivity.class );
    }

    @Override
    public HashMap<String, String> getMethodMap(a) {
        return routerMethodMap;
    }

    @Override
    publicHashMap<String, Class<? >> getClassMap() {returnrouterClassMap; }}Copy the code
  • Inject the routing table ExampleAotIndex after the Application starts, typically in Application:
AotLoader.enableLog(true);// Whether to start logging
AotLoader.addRouter(new ExampleAotIndex());// Inject the route table for the load method
Copy the code
  • The framework abstracts the method of loading data into a production and consumption task, a typical producer-consumer model. Aotloader.produce (methodRouter) when the task that loaded the data is produced before the Activity is started, the method that declared the annotated route is located according to the route name of the method passed to it, and then the reflected call is executed. The return value of aotLoader.produce (methodRouter) is the ID of the task, which is passed to the Activity as a parameter
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);
}
Copy the code
  • Once the Activity is initialized and the View is ready, you can consume preloaded data based on the ID of the passed task:
    aotTaskId = getIntent().getStringExtra(START_AOT_LOAD_ID);
    if(AotLoader.isValidTask(aotTaskId)){
        AotLoader.consume(aotTaskId, listener);
    }
Copy the code