The source code integration practice of EventBus, how to modify the package name of the EventBus source code, and integrate atp into your own project

demand background

  • Recently, I made a request that we need to integrate EventBus into our own project. Since we are doing SDK, the library provided to users should not have too many third-party dependent libraries, otherwise it is easy to send when others access your SDK. Conflict, we will not use gradle for dependencies, but switch to the EventBus source code method. In order to improve the execution efficiency of EventBus, we also introduce apt. Let’s talk about the specific practice below.

Understanding EventBus

EventBus source code integration

  • We use git clone  https://github.com/greenrobot/EventBus.git to copy the source code locally, then use Android studio to open it, and then copy the source code we need to use under the project package name we defined
  •  Build a module in our project, for example, it is called lcqlib, and then copy the source code in the two moduls above EventBus to the com.lcq.lcqlib.msgbus package path
  • Then we need to solve the reported red exception, here is a quick way to find and replace
  • In this way, you can find all the places used and replace them all 
  • Use Replace All to replace all the code, and then we will find the AndroidDependenciesDetector class
  • Then search for "org.greenrobot.eventbus" and replace this location with "com.lcq.lcqlib.msgbus.org.greenrobot.eventbus", or an exception will be thrown when executing later
  • Then we assemble the module again, and it can be compiled normally. For the convenience of use, we have to package this library. Since there are only source codes and no resource files, let’s package it directly into a jar package. This jar will be called apt later. also used when
  • To easily generate jar and define the name, the best way is to write a task to run the best
  • makejar is used to generate the jar we need
    task makeJar(group: 'build', type: Copy) {
        String libName = "${project.name}_3.3.2.jar"
        delete "build/libs/${libName}"
        from('build/intermediates/aar_main_jar/release')
        into('build/libs/')
        include('classes.jar')
        rename('classes.jar', libName)
    }
    makeJar.dependsOn(build)

    We execute the makejar task to generate a lcqlib_3.3.2.jar for subsequent use

APT source code integration of EventBus

  • In order to improve the efficiency of EventBus code execution, we also need to use the APT method. For the use of EventBus APT, please refer to this Subscriber Index - Open Source by greenrobot
  • The official website is used like this

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

android {

    defaultConfig {

        javaCompileOptions {

            annotationProcessorOptions {

                arguments = [ eventBusIndex : 'com.example.myapp.MyEventBusIndex' ]

            }

        }

    }

}

dependencies {

    def eventbus_version = '3.2.0'

    implementation "org.greenrobot:eventbus:$eventbus_version"

    annotationProcessor "org.greenrobot:eventbus-annotation-processor:$eventbus_version"

}

  • Of course, this method is definitely not good for the way we use the source code. The apt of EventBus is implemented by annotating its own source code. Now that we have changed the source code package name, it will definitely not work. Now we need I imitated the APT source code of EventBus to implement it by myself. It is actually very simple. Let's implement the following
  • First find the EventBusAnnotationProcessor project in the EventBus source code project, and then copy the source code inside
  • We build a module of java library type in our own project, and then copy the source code of EventBusAnnotationProcessor into it
  •  You can see that the report is red, there is only one class in it, let's look at the place where the report is red
  • It should be that some dependencies are missing and the import org.greenrobot.eventbus.Subscribe inside needs to be replaced with our own defined class. Copy the lcqlib_3.3.2.jar generated above to the lib directory of lcqlib, and the import dependency is com.lcq. lcqlib.msgbus.org.greenrobot.eventbus.Subscribe and com.lcq.lcqlib.msgbus.org.greenrobot.eventbus.ThreadMode,
  • Then we look at the source code of the EventBusAnnotationProcessor class and search for "import org.greenrobot.eventbus." We need to replace this code with "com.lcq.lcqlib.msgbus.org.greenrobot.eventbus." The purpose of this is Use the class in our own source code, otherwise it will report an exception that cannot find the class
  •  modified code
  • It is also necessary to modify the place of this annotation, and also change it to the package name of our source code
  • After modifying the source code, we need to configure the full path with the package name of the EventBusAnnotationProcessor class to the res/META-INFO/services/javax.annotation.processing.Processor file. This is very important. If not configured, when using apt later will not work as shown in the image below
  • Next, you need to configure the second and third-party libraries that apt depends on in the lcqapt module build.gradle. as follows
    apply plugin: 'java'
    
    group = rootProject.group
    version = rootProject.version
    
    java.sourceCompatibility = JavaVersion.VERSION_1_8
    java.targetCompatibility = JavaVersion.VERSION_1_8
    
    dependencies {
        implementation files('libs/lcqlib_3.3.2.jar')
        implementation 'de.greenrobot:java-common:2.3.1'
    
        // Generates the required META-INF descriptor to make the processor incremental.
        def incap = '0.2'
        implementation "net.ltgt.gradle.incap:incap:$incap"
        implementation "net.ltgt.gradle.incap:incap-processor:$incap"
        annotationProcessor "net.ltgt.gradle.incap:incap-processor:$incap"
    }
    
    sourceSets {
        main {
            java {
                srcDir 'src'
            }
            resources {
                srcDir 'res'
            }
        }
    }
    
    javadoc {
        title = "EventBus Annotation Processor ${version} API"
        options.bottom = 'Available under the Apache License, Version 2.0 - <i>Copyright &#169; 2015-2020 <a href="https://greenrobot.org">greenrobot.org</a>. All Rights Reserved.</i>'
    }
    
    task javadocJar(type: Jar, dependsOn: javadoc) {
        archiveClassifier.set("javadoc")
        from 'build/docs/javadoc'
    }
    
    task sourcesJar(type: Jar) {
        archiveClassifier.set("sources")
        from sourceSets.main.allSource
    }
    apply plugin: 'com.github.johnrengelman.shadow'
    shadowJar {
        manifest {  //main方法所在的类
        }
    }
    
    
    
  •  dependencies{} configures the dependent libraries used
  • The "src" and "res" paths are configured in sourceSets
  • apply plugin: 'com.github.johnrengelman.shadow' is used to package the generated apt into a jar package. To use this gradle plugin, you need to configure the build.gradle in the root directory as follows
    // Top-level build file where you can add configuration options common to all sub-projects/modules.
    buildscript {
        repositories {
            google()
            jcenter() //shadow插件用到的仓库
            mavenCentral()
        }
        dependencies {
            classpath "com.android.tools.build:gradle:7.0.3"
    
            //shadow 插件的配置
            classpath 'com.github.jengelman.gradle.plugins:shadow:4.0.0'
            // NOTE: Do not place your application dependencies here; they belong
            // in the individual module build.gradle files
        }
    }
    
    task clean(type: Delete) {
        delete rootProject.buildDir
    }
  • After configuration, we execute the shadowJar task, which will generate the apt plugin jar package we need
  •  We copy the generated lcqapt.jar to the module or project that needs to be used, and then configure it to use it

How to use the EventBus and apt library built by yourself

  • The above series of operations mainly created two libraries, lcqlib and lcqapt, and the generated jar package products are lcqlib_3.3.2.jar and lcqapt.jar. Let’s see how to use them in the demo
  • First of all, we must introduce the jar package we generated into the project. Copy lcqlib_3.3.2.ja to the libs directory, and copy lcqapt.jar to the libs_apt directory. The main reason why lcqapt.jar is not copied to the libs directory is to prevent it from being generated. When compiling the apk or aar package, this is only used to generate code for us, and it is only used in the compilation phase
  • Then configure the dependencies in the app's build.gradle and the classes to be generated
    plugins {
        id 'com.android.application'
    }
    
    android {
        compileSdk 30
    
        defaultConfig {
            applicationId "com.lcq.lcqeventbus"
            ...
    
            javaCompileOptions {
                annotationProcessorOptions {
                    //指定辅助索引类的名称和包名 EventBus config
                    arguments = [eventBusIndex: 'com.lcq.lcqeventbus.MyEventBusIndex']
                }
            }
        }
    
        ...
    }
    
    dependencies {
        ...
    
        //EventBus config
        api files("libs/lcqlib_3.3.2.jar")
        annotationProcessor files("/libs_apt/lcqapt.jar")
    }
  • After the configuration is complete, you need to write the code. We will test it in the MainActivity in the app module and write the following code. If you are not clear about the use of EventBus, you can go to the official website to learn
    package com.lcq.lcqeventbus;
    
    import androidx.appcompat.app.AppCompatActivity;
    
    import android.os.Bundle;
    import android.view.View;
    import android.widget.Toast;
    
    import com.lcq.lcqlib.msgbus.org.greenrobot.eventbus.EventBus;
    import com.lcq.lcqlib.msgbus.org.greenrobot.eventbus.Subscribe;
    
    
    public class MainActivity extends AppCompatActivity {
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            EventBus.builder()
                    .addIndex(new MyEventBusIndex())
                    .installDefaultEventBus();
            EventBus.getDefault().register(this);
        }
    
        @Subscribe
        public void handleMsg(String msg) {
            Toast.makeText(this, "msg:" + msg, Toast.LENGTH_LONG).show();
        }
    
        public void onClick(View v) {
            EventBus.getDefault().post("HELLO,EventBus APT");
        }
    }
  • The result after running is as follows:

    Summary: The whole process is quite cumbersome, and there are many error-prone places, and many third-party gradle plug-ins or scripts are used, but once the framework is built, it will basically not change much later, and it is used in the same way as the original EventBus It is almost exactly the same, achieving the purpose of modifying the source code package name, so that the SDK sent out will not worry about conflicts with the receiving party, and you can also modify the EventBus source code according to your own needs, so that the Wheel of EventBus is integrated into our own project in progress

 

Guess you like

Origin blog.csdn.net/qq_19942717/article/details/125065981