JDispatcher

Android component lifecycle distribution framework, suitable for componentization, modularization, startup optimization and other scenarios

Github : JDispatcher

Function is introduced

  • The implementation of Application lifecycle methods is distributed among all required components

  • Distribution order supports multiple rules

    • Priority: The higher the priority value, the earlier it is called

    • Dependencies: Component-dependent distribution classes are initialized first

    • Support for automatic correction of distribution order in case of cross-use of priority and dependency rules

  • The distribution dimension supports multiple rules

    • Distributed in the specified process (all, master, non-master)

    • Distributed in a specified thread (main thread, idle thread, worker thread) to achieve asynchronous loading

    • Support for cross-use of asynchronous and synchronous loading via non-blocking asynchronous notification (TODO)

    • Manual delay call distribution to achieve lazy loading

    • Pre-loading (Todo) before Application via ContentProvider

    • It is distributed only in debug mode to initialize development tools such as DevTools and DoKit

  • The dimensional value adopts the bit operation of integer OR/AND to complete the collection and recognition of dimensional value, which is flexible and efficient

  • Supports batch parameter transfer during initialization, which can be used for the initialization of the three-party SDK of multiple projects and multiple environments, making the environment configuration more unified

  • With annotation points, APT incrementally collects and distributes classes to reduce coupling and can be used in modular, componentized scenarios

  • Improve runtime performance by intercepting the AGP build process to scan and sort the distribution classes at compile time

  • AGP Transform Increments support compilation (TODO)

  • The automatic injection of publishing and Application lifecycle callback method is realized by ASM bytecode staking, and the integration is more efficient

  • Supports statistics on the initialization time of all distribution classes, which can be used to start optimized statistics and troubleshooting

Frame structure

  • jdispatcher-annotation

    • Module type: apply plugin: ‘Java’

    • Module description: declare annotation classes and public classes required at compile time

  • jdispatcher-compiler

    • Module type: apply plugin: ‘Java’

    • Compile time (.java–.class phase) collect and process Dispatch annotation information in the whole project and generate auxiliary class file JDispatcher$$group_hash.java via Javapoet

  • jdispatcher-plugin

    • Module type: apply plugin: ‘groovy’

    • Custom Transform intercepts the AGP build process at compile time (.class–.dex stage), finds all dispatches and sorts them

    • Main tasks of the module:

      • The first one is the distribution process of IDispatch

        • All APT generated JDispatcher$$group_hash. Java files are scanned

        • Map<String, DispatchItem> atlas)

        • Reflection instantiation of IDispatch object is realized through DispatchItem collected by Atlas collection

        • Sort operations according to DispatchItem sorting rules

        • The ordered SET of IDISpatches is inserted into JDispatcher by bytecode, and the distribution operation of all IDispatches is performed at runtime

      • Second: automatic registration process for Application lifecycle methods

        • The class is scanned in the custom Transform using the Application full class name configured by the caller in Gradle

        • JDispatcher calls bytecode injection to onTerminate()

        • JDispatcher calls bytecode injection to onConfigurationChanged(newConfig: Configuration)

        • JDispatcher calls bytecode injection into onLowMemory()

        • JDispatcher calls bytecode injection into onTrimMemory(level: Int)

  • jdispatcher-api

    • Module type: apply plugin: ‘com.android.library’

    • Runtime is used for initialization of the entire framework, runtime distribution and other operations

Integrated description

//Step 1. Add the JitPack repository to your build file
//buildscript & allprojects
allprojects {
    repositories {
        ...
        maven { url 'https://jitpack.io' }
    }
}
//dependencies
classpath 'com.github.jaydroid1024.JDispatcher:jdispatcher-plugin:$last_version'

//Step 2. Add the dependency
implementation 'com.github.jaydroid1024.JDispatcher:jdispatcher-api:$last_version'
kapt 'com.github.jaydroid1024.JDispatcher:jdispatcher-compiler:$last_version'

//Step 3. apply the plugin and config dispatcher
apply plugin: 'jdispatcher'
dispatcher {
    appCanonicalName = "com.jay.android.App"
    buildIncremental = false
    buildDebug = true
}
Copy the code

Directions for use

class App : Application() {override fun onCreate() {super.oncreate () Val dispatchExtraParam = HashMap<String, HashMap<String, String>>() dispatchExtraParam["com.jay.android.jdispatcher.DispatcherAppDemo"] = if (BuildConfig.DEBUG) hashMapOf( Pair("key1", "value1_debug"), Pair("key2", "value2_debug") ) else hashMapOf( Pair("key1", "value1_release"), Pair("key2", "value2_release")) jDispatcher.instance. WithDebugAble (true) Print more logs, WithDispatchExtraParam (dispatchExtraParam)// dispatch parameter.init(this)} // region if // dispatcher is configured in app build.gradle {appCanonicalName = "com.jay.android.app "}} override Fun onTerminate() { super.onTerminate() JDispatcher.instance.onTerminate() } override fun onConfigurationChanged(newConfig: Configuration) { super.onConfigurationChanged(newConfig) JDispatcher.instance.onConfigurationChanged(newConfig) } override fun onLowMemory() { super.onLowMemory() JDispatcher.instance.onLowMemory() } override fun onTrimMemory(level: Int) { super.onTrimMemory(level) JDispatcher.instance.onTrimMemory(level) } //endregion }Copy the code
/ / manual call distribution JDispatcher. Instance. ManualDispatch (" com. Jay. Android. JDispatcher. DispatcherAppDemo ")Copy the code

··· // Declare the Dispatch class @dispatch (priority = priority.LOW_DEFAULT, description = “DispatcherAppDemo”) public class DispatcherAppDemo extends DispatchTemplate {

@Override
public void onCreate(@NotNull Application app, @NotNull DispatchItem dispatchItem) {
    Log.d("Jay", "DispatcherAppDemo#onCreate" + dispatchItem);
}

@Override
public void onConfigurationChanged(@NotNull Configuration newConfig) {
    Log.d("Jay", "DispatcherAppDemo#onConfigurationChanged" + newConfig);
}

@Override
public void onLowMemory() {
    Log.d("Jay", "DispatcherAppDemo#onLowMemory");

}

@Override
public void onTerminate() {
    Log.d("Jay", "DispatcherAppDemo#onTerminate");

}

@Override
public void onTrimMemory(int level) {
    Log.d("Jay", "DispatcherAppDemo#onTrimMemory" + level);

}
Copy the code

}

# Jdispatcher confusion configuration - keep public class com. Jay. Android. The dispatcher. {* * *; } -keep class * implements com.jay.android.dispatcher.common.IDispatch{*; }Copy the code

Todo

  • Supports cross-use of asynchronous and synchronous loading through non-blocking asynchronous notification mechanism

  • Implement pre-loading ahead of Application via ContentProvider

  • AGP Transform deltas support compilation

reference

  • ARouter is a framework for componentizing Android apps — enabling routing, communication, and decoupling between modules

  • AppInit is an Android application initialization framework. It is based on the componentized design idea, flexible and easy to use.

  • WMRouter is an Android routing framework based on componentized design. It is flexible and easy to use.