Android性能優(yōu)化之如何優(yōu)雅的計(jì)算耗時(shí)?

前言

?性能優(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í)間)。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容