Giter Site home page Giter Site logo

crepecake's Introduction

CrepeCake

A compile-time aop engine like AspectJ but easier to use in android application development.

GitHub license Android Weekly Recommend

Wiki


First At A Glance : ]

Here is am example that injected the onCreate() Method in MainActivity:

@Aspect(MainActivity.class)
public class MainActivityAspect {

    protected void onCreate(InvocationHandler invocationHandler, Bundle savedInstanceState) {
      System.out.println("⇢ onCreate");
      long startTime = System.currentTimeMillis();
      invocationHandler.invoke(savedInstanceState);
      System.out.println(String.format("⇠ onCreate [%dms]", System.currentTimeMillis() - startTime));    
    }

}

That's all,these code will be executed during the onCreate method in MainActivity with printing the running time of it:

I/System.out: ⇢ onCreate
I/System.out: ⇠ onCreate [33ms]

Installation

  1. Add the buildscript dependencies in the root project:
buildscript {

  repositories {
      google()
      jcenter()
  }
  dependencies {
      classpath 'com.android.tools.build:gradle:3.0.1'
      classpath 'net.idik.crepecake:plugin:0.0.4' // Add Here
  }

}
  1. Add crepecake plugin in the target module

The crepecake plugin MUST AFTER(VERY IMPORTANT) the application plugin

// Apply application or library plugin here...
apply plugin: 'net.idik.crepecake'

Usage

  1. Programme the injection processor on the basis of target class, with the annotation @Aspect
@Aspect(MainActivity.class)
public class MainActivityAspect {
  // injection methods...
}
  1. Programme the injection method

    Step 1. Declare the injection method with the target method infos, including the access level, static or not, name of method, parameters.

    Step 2. Insert InvocationHandler invocationHandler at the 1st position of the parameter list

    Done.

    @Aspect(MainActivity.class)
    public class MainActivityAspect {
    
        protected void onCreate(InvocationHandler invocationHandler, Bundle savedInstanceState) {
          System.out.println("⇢ onCreate");
          long startTime = System.currentTimeMillis();
          invocationHandler.invoke(savedInstanceState);
          System.out.println(String.format("⇠ onCreate [%dms]", System.currentTimeMillis() - startTime)); 
        }
    
        public android.support.v7.app.ActionBar getSupportActionBar(InvocationHandler invocationHandler) {
            ActionBar bar = (ActionBar) invocationHandler.invoke();
            //do stuff...
            return bar;
        }
    
        //other injection methods...
    }

So far, we have completed the job that injects the onCreate(Bundle savedInstanceState)getSupportActionBar() and other methods in the MainActivity.

InvocationHandler is a flag indicating this is an injection method. Beside, we could invoke the original method through it and obtain the result(if return type is not void).

AspectConfig

We could customize the injection points by inheriting the AspectConfig class

public class OnClickAspectConfig extends AspectConfig {
    @Override
    protected boolean isEnable() {
        return super.isEnable();
    }

    @Override
    public boolean isHook(Class clazz) {
        return View.OnLongClickListener.class.isAssignableFrom(clazz) || View.OnClickListener.class.isAssignableFrom(clazz);
    }
}

The above codes means that we will inject ALL the subClass of OnLongClickListener and OnClickListener.

⚠️ Attention: The AspectConfig class will be executed during the compile-time, so do not make any running-time logic within it.

Then, use it to the injection processor with the annotation @Aspect

@Aspect(OnClickAspectConfig.class)
public class OnClickListenerAspect {
  public void onClick(InvocationHandler invocationHandler, View view) {
      System.out.println("OnClick: " + view);
      invocationHandler.invoke(view);
  }

  public boolean onLongClick(InvocationHandler invocationHandler, View view) {
      boolean isConsume = (boolean) invocationHandler.invoke(view);
      if (isConsume) {
          System.out.println("OnLongClick: " + view);
      }
      return isConsume;
  }
}

See more...

Great Thanks to...


先撇一眼 : ]

举个例子注入MainActivity的onCreate方法:

@Aspect(MainActivity.class)
public class MainActivityAspect {

    protected void onCreate(InvocationHandler invocationHandler, Bundle savedInstanceState) {
      System.out.println("⇢ onCreate");
      long startTime = System.currentTimeMillis();
      invocationHandler.invoke(savedInstanceState);
      System.out.println(String.format("⇠ onCreate [%dms]", System.currentTimeMillis() - startTime));    
    }

}

这就完成了对MainActivity的注入,以上代码会输出onCreate的运行时间:

I/System.out: ⇢ onCreate
I/System.out: ⇠ onCreate [33ms]

安装

  1. 在root project的buildscript中添加dependencies如下:
buildscript {

  repositories {
      google()
      jcenter()
  }
  dependencies {
      classpath 'com.android.tools.build:gradle:3.0.1'
      classpath 'net.idik.crepecake:plugin:0.0.4' //添加在此
  }

}
  1. 在目标模块的build.gradle文件中添加插件(请务必添加于Application插件后)如下:
// apply application or library plugin here
apply plugin: 'net.idik.crepecake'

用法

  1. 根据目标类,编写注入处理器,通过@Aspect指定目标类
@Aspect(MainActivity.class)
public class MainActivityAspect {
  // 注入方法们...
}
  1. 编写注入方法,步骤如下

    Step 1. 声明注入方法与目标方法声明一致,包括访问属性、静态、方法命名、参数列表等
    Step 2. 添加InvocationHandler invocationHandler至参数列表第一位
    Done.

    @Aspect(MainActivity.class)
    public class MainActivityAspect {
    
        protected void onCreate(InvocationHandler invocationHandler, Bundle savedInstanceState) {
          System.out.println("⇢ onCreate");
          long startTime = System.currentTimeMillis();
          invocationHandler.invoke(savedInstanceState);
          System.out.println(String.format("⇠ onCreate [%dms]", System.currentTimeMillis() - startTime));
        }
    
        public android.support.v7.app.ActionBar getSupportActionBar(InvocationHandler invocationHandler) {
            ActionBar bar = (ActionBar) invocationHandler.invoke();
            //do stuff...
            return bar;
        }
    
        //other inject methods...
    }

至此,我们已经完成了对MainActivity的onCreate(Bundle savedInstanceState)getSupportActionBar()以及其他方法的切面注入。

InvocationHandler这个参数很重要,这个参数标志着这是一个注入方法,并且通过这个参数,我们可以调用目标方法,并获取返回值(如果非void

AspectConfig

通过继承AspectConfig对象可以对注入点进行个性化的定制,如下:

public class OnClickAspectConfig extends AspectConfig {
    @Override
    protected boolean isEnable() {
        return super.isEnable();
    }

    @Override
    public boolean isHook(Class clazz) {
        return View.OnLongClickListener.class.isAssignableFrom(clazz) || View.OnClickListener.class.isAssignableFrom(clazz);
    }
}

其中,isHook方法判断该类是否为目标类,在上述代码中指定了OnLongClickListenerOnClickListener所有子类都为注入目标,我们可以通过该方法进行定制。

⚠️ 注意:这个类将会在编译时被调用,请不要在此类中做运行时动态逻辑。

写完配置类后,在注入类上通过@Aspect注解应用即可

@Aspect(OnClickAspectConfig.class)
public class OnClickListenerAspect {
  public void onClick(InvocationHandler invocationHandler, View view) {
      System.out.println("OnClick: " + view);
      invocationHandler.invoke(view);
  }

  public boolean onLongClick(InvocationHandler invocationHandler, View view) {
      boolean isConsume = (boolean) invocationHandler.invoke(view);
      if (isConsume) {
          System.out.println("OnLongClick: " + view);
      }
      return isConsume;
  }
}

查看更多...

万分感谢


License

Copyright 2017 认真的帅斌

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

   http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

crepecake's People

Contributors

linisme avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

crepecake's Issues

I add the @aspect notation to aspectclasss no compile

Captssura
@aspect(MainActivity.class)
my proyect no compile, this is my gradle project
`// Top-level build file where you can add configuration options common to all sub-projects/modules.

buildscript {
repositories {
google()
jcenter()

}
dependencies {
    classpath 'com.android.tools.build:gradle:3.3.1'
    classpath 'net.idik.crepecake:plugin:0.0.4' // Add Here
    // NOTE: Do not place your application dependencies here; they belong
    // in the individual module build.gradle files
}

}

allprojects {
repositories {
google()
jcenter()

}

}

task clean(type: Delete) {
delete rootProject.buildDir
}`

gradle module
`apply plugin: 'com.android.application'
apply plugin: 'net.idik.crepecake'
android {
compileSdkVersion 29
buildToolsVersion "29.0.0"
defaultConfig {
applicationId "com.planensas.myapplication"
minSdkVersion 15
targetSdkVersion 29
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
}

dependencies {
//versions
def roomVersion = '2.1.0-alpha06'
def archLifecycleVersion = '2.0.0'
def lifecycle_version = "2.0.0"

implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'androidx.appcompat:appcompat:1.0.0-beta01'
implementation 'androidx.constraintlayout:constraintlayout:1.1.2'

implementation 'com.google.android.material:material:1.1.0-alpha04'
implementation 'com.android.support:appcompat-v7:29.0.0'
implementation 'com.android.support:design:29.0.0'
implementation 'com.android.support:cardview-v7:29.0.0'
// ViewModel and LiveData
implementation "androidx.lifecycle:lifecycle-extensions:$lifecycle_version"
// Room components
implementation "androidx.room:room-runtime:$roomVersion"
annotationProcessor "androidx.room:room-compiler:$roomVersion"
androidTestImplementation "androidx.room:room-testing:$roomVersion"
// Lifecycle components
implementation "androidx.lifecycle:lifecycle-extensions:$archLifecycleVersion"
annotationProcessor "androidx.lifecycle:lifecycle-compiler:$archLifecycleVersion"

// retrofit
implementation 'com.squareup.retrofit2:retrofit:2.1.0'
implementation 'com.squareup.retrofit2:converter-gson:2.1.0'
//

//test
testImplementation 'junit:junit:4.12'
androidTestImplementation 'androidx.test:runner:1.1.0-alpha4'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.0-alpha4'

}`

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.