前言
?性能優(yōu)化的方向之一就是計(jì)算方法的耗時(shí),去分析初始化所耗時(shí)間是否和預(yù)期差不多。耗時(shí)計(jì)算方法可以分為手動(dòng)打點(diǎn)和AOP打點(diǎn),手動(dòng)打點(diǎn)可以查看Android性能優(yōu)化之App啟動(dòng)優(yōu)化,本文主要講述的是AOP打點(diǎn)方法。
一、什么是AOP?
?AOP為Aspect Oriented Programming的縮寫,意為:面向切面編程,通過(guò)預(yù)編譯方式和運(yùn)行期間動(dòng)態(tài)代理實(shí)現(xiàn)程序功能的統(tǒng)一維護(hù)的一種技術(shù)。利用AOP可以對(duì)業(yè)務(wù)邏輯的各個(gè)部分進(jìn)行隔離,從而使得業(yè)務(wù)邏輯各部分之間的耦合度降低,提高程序的可重用性,同時(shí)提高了開(kāi)發(fā)的效率。
?OOP、AOP都是編程思想,沒(méi)有具體的語(yǔ)言實(shí)現(xiàn)。我們可以從看問(wèn)題的角度去理解OOP和AOP,OOP是將屬性、細(xì)節(jié)封裝成對(duì)象,可以稱之為模塊化。而AOP是將需要統(tǒng)一處理的事務(wù)集中起來(lái)做處理,例如在某個(gè)相同的方法前都需要做一件事(打印日志),做這件事其實(shí)就是AOP編程思想的體現(xiàn)。使用AOP去處理問(wèn)題有以下兩點(diǎn)好處:
1.針對(duì)同一類問(wèn)題統(tǒng)一處理(例如性能問(wèn)題,需要在所有Activity的Oncreate方法中進(jìn)行打點(diǎn))
2.無(wú)侵入添加代碼(手動(dòng)打點(diǎn)侵入性強(qiáng))
二、如何使用AOP?
?Android中我們常用的AOP的框架是AspectJ,集成步驟如下:
?1.插件引用
在項(xiàng)目根目錄的build.gradle里依賴AspectJX
dependencies {
classpath 'com.hujiang.aspectjx:gradle-android-plugin-aspectjx:2.0.8'
}
?2.添加到包含有AspectJ代碼的module.
implementation 'org.aspectj:aspectjrt:1.8.+'
?3.在app項(xiàng)目的build.gradle里應(yīng)用插件
apply plugin: 'android-aspectjx'
//或者這樣也可以
apply plugin: 'com.hujiang.android-aspectjx'
三、AspectJ相關(guān)知識(shí)點(diǎn)
JoinPoints
?程序運(yùn)行時(shí)的執(zhí)行點(diǎn),可以作為切面的地方,例如:
1.函數(shù)調(diào)用、執(zhí)行的地方
2.獲取、設(shè)置變量
3.類初始化
PointCut
?帶條件的JoinPoints,通過(guò)設(shè)置條件篩選出我們需要的切面。
Advice
?插入代碼的位置。常用的三種語(yǔ)法類型:
1.Before:PointCut之前執(zhí)行
2.After:PointCut之后執(zhí)行
3.Around:PointCut之前之后分別執(zhí)行
語(yǔ)法介紹
@Before("execution(* android.app.Activity.on**(..))")
public void onActivityCalled(JoinPoint joinPoint) throw Throwable{
//todo
}
1.Before:Advice,具體插入位置
2.execution:處理Join Point的類型,例如:call、execution。
call
在方法調(diào)用的地方插入
class MainActivity() {
//調(diào)用方法的地方插入
Log.d("msg","before insert")
init()
Log.d("msg","after insert")
}
execution
在方法內(nèi)部插入
class MainActivity : AppCompatActivity() {
//調(diào)用方法
init()
}
private fun init() {
//方法內(nèi)部插入
Log.d("msg","before insert")
//TODO 搞事情
Log.d("msg","after insert")
}
3.android.app.Activity.on**(..):*表示的是返回值它的意思是可以任意返回值,匹配所有android.app.Activity.on開(kāi)頭的方法,(..)表示無(wú)論有無(wú)參數(shù)都進(jìn)行匹配
4.onActivityCalled:要插入的代碼。
四、AOP實(shí)踐
如何取得聯(lián)系?
?使用@Aspect注解定義文件就可以讓AspectJ在編譯期自動(dòng)去解析文件。
@Aspect
class PerformanceAop {
@Around("call(* com.example.myapplication.MyApplication.**(..))")
fun getTime(joinPoint: ProceedingJoinPoint) {
val signature = joinPoint.signature
val time = System.currentTimeMillis()
joinPoint.proceed()
Log.d("msg---" + signature.name, "${System.currentTimeMillis() - time}MS")
}
}
class MyApplication() : Application() {
override fun onCreate() {
super.onCreate()
initBugly()
initUmeng()
initBaidu(false);
}
private fun initBaidu(b: Boolean) {
Thread.sleep(100)
}
private fun initUmeng() {
Thread.sleep(200)
}
private fun initBugly() {
Thread.sleep(300)
}
}
?執(zhí)行結(jié)果:

joinPoint.proceed()手動(dòng)執(zhí)行一次代碼,Around與Before、After不同點(diǎn)就在于此。我們可以在切面執(zhí)行之前和之后做一些事(計(jì)算方法執(zhí)行時(shí)間)。