SoFunction
Updated on 2025-03-01

Detailed explanation of Android section programming knowledge points

Sectional programming may sound a bit strange, but more and more development teams are using this technology now.

Let’s talk about familiar object-oriented programming. OOPs usually use various objects/modules to be responsible for specific functions and try not to couple them.

AOP (aspect-priented programming) is a result of the problem that coupling cannot be resolved in OOP.

For example, there are several modules in the project responsible for network/data storage/UI, and each module is connected to another Log module.

Although Log does not belong to the first three functions, because they are all connected, they are coupled to some extent. When modifying the implementation of the Log module, it will affect the implementation of the other three modules.

This article uses the simplest example to describe how AOP solves this problem.

(Actually, this is an AspectJ environment configuration guide)

Install AspectJ

ApsectJ development on Android consists of several parts, AspectJ gradle plug-in, ApsectJ dependencies, and AspectJ compiler.

First of all, installing the AspectJ compiler is very simple, just like installing the JAVA environment.

Download link:/downloads/?file=/tools/aspectj/aspectj-1.9.

The latest one has been updated to 1.9.1. If your computer already has a JAVA environment, just run this jar package.

After the installation is completed, you need to configure the environment variables to the bin directory of aspectj. I will not repeat it here

export PATH="$PATH:~/Library/Android/sdk/platform-tools"
export PATH="$PATH:/usr/local/opt/gradle/gradle-4.1/bin"
export PATH="$PATH:~/Library/Android/sdk/ndk-bundle"
export PATH="$PATH:~/Library/flutter/bin"
export PATH="$PATH:~/Library/kotlinc/bin"
export PATH="$PATH:~/Library/AspectJ/bin" <- AspectJofPATH

After the configuration is completed, you should see the corresponding output

AspectJ Compiler 1.9.0 (1.9.0 - Built: Monday Apr 2, 2018 at 18:52:10 GMT)

Configure Android Gradle to add AspectJ dependencies

The process of building an Android App with AspectJ support is to first compile the .class file according to the normal process, and then use the ajc compiler to insert the code we need into the .class file.

First, you need to add AspectJ dependencies to the gradle root directory.

buildscript {
  repositories {
    google()
    jcenter()
  }
  dependencies {
    classpath ':gradle:3.1.2'
    classpath ':aspectjtools:1.8.9' //Aspect
    classpath ':aspectjweaver:1.8.9' //Aspect
  }
}

Then add the following content to the project app directory,

apply plugin: ''
//+Add contentimport 
import 
buildscript {
  repositories {
    mavenCentral()
  }
  dependencies {
    classpath ':aspectjtools:1.8.9'
    classpath ':aspectjweaver:1.8.9'
  }
}
repositories {
  mavenCentral()
}

final def log = 
final def variants = 
 { variant ->
  if (!()) {
    ("Skipping non-debuggable build type '${}'.")
    return;
  }

  JavaCompile javaCompile = 
   {
    String[] args = ["-showWeaveInfo",
             "-1.8",
             "-inpath", (),
             "-aspectpath", ,
             "-d", (),
             "-classpath", ,
             "-bootclasspath", ()]
    MessageHandler handler = new MessageHandler(true);
    new Main().run(args, handler);
  }
}
//-Add content

This gradle script is to add an acj compilation process after Java compilation is completed.

MessageHandler is an object in AspectJ Tools, used to receive parameters and then compile acj.

Finally, just add dependencies dependencies to support AspectJ.

implementation ':aspectjrt:1.9.0'

Create AspectJ code

The following part of the code looks confused, but don't worry about the specific syntax meaning for now.

First run into the environment, and then combine the theory to slowly modify the code and then quickly get started with AOP.

Taking HelloWorld as an example, we don’t do anything in our MainActivity, only the basic life cycle method.

public class MainActivity extends AppCompatActivity {
  @Override
  protected void onCreate(Bundle savedInstanceState) {
    (savedInstanceState);
    setContentView(.activity_main);
  }

  @Override
  protected void onStart() {
    ();
  }

  @Override
  protected void onPause() {
    ();
  }

  @Override
  protected void onStop() {
    ();
  }

  @Override
  protected void onDestroy() {
    ();
  }
}

Now we want to write an AspectJ class. This class looks a bit different from ordinary Java classes. It can be understood that it just uses annotations as a medium to let the ACJ compiler know which methods to inject.

What this class needs to do is tell the ACJ compiler to print a line of log in front of each method in MainActivity and output which method is currently executing.

@Aspect
public class AspectTest {
  private static final String TAG = "AspectTest";

  @Pointcut("execution(* .**(..))")
  public void executeAspectJ() {
  }

  @Before("executeAspectJ()")
  public void beforeAspectJ(JoinPoint joinPoint) throws Throwable {
    (TAG, "beforeAspectJ: injected -> " + ());
  }
}

The first time I came into contact with AspectJ, I was a little confused when I saw this code. I will explain the meaning of several annotations.

  • @Aspect: Tell ACJ compiler this is an AspectJ class
  • @PointCut: PointCut is a concept in AspectJ. Another concept with it is JoinPoint. These two concepts together describe the cut face to be injected
  • @Before: Indicates the location to be injected. Commonly used ones include Before/After/Around, which respectively represent before, after, and replace the original method.

The parameter annotated by @PointCut here means injecting all methods in MainActivity, and the parameters are using regular matching syntax.

Let's see the results of this code execution

07-26 16:04:56.611 22823-22823/? D/AspectTest: beforeAspectJ: injected -> execution((..))
07-26 16:04:56.661 22823-22823/? D/AspectTest: beforeAspectJ: injected -> execution(())

I saw that although we did not write a log print statement in MainActivity, it was implemented through AspectJ, and our own log was inserted before the MainActivity two life cycles were executed.

Use scenarios

AspectJ is just one of AOP's methods, and similarly, it also uses asm to modify the bytecode. The reason why AOP has become more and more people understand it is that it can be very well decoupled in abstract terms.

Advanced points can be used to use AOP to realize traceless burial points, data collection, and even modify codes that cannot be moved in the SDK.

The entire DEMO code above can be obtained from GitHub, and the download link can be obtained by replying to "section" in the background.