kotlin中使用AOP

本文介绍了在Kotlin中如何使用AOP进行面向切面编程,包括其概念、应用场景,如权限申请、日志统计等,并提供了一个简单的按钮双击防护的示例及一个权限控制框架的实现,详细讲解了注解、切面类和功能类的使用。

一.前言:AOP(Aspect Orented Programming):面向切面编程,通过ajc编译器把java文件编译为加工过的class文件,个人感觉就是定点插入代码。
二.应用场景:权限申请,日志统计,行为统计,性能检测。
三.项目配置:这里我放在公共模块中
(1)project中添加:

  classpath 'com.hujiang.aspectjx:gradle-android-plugin-aspectjx:2.0.4'

(2)主module中

     apply plugin: 'com.hujiang.android-aspectjx'
***
    implementation 'org.aspectj:aspectjrt:1.8.13'

(3)common module中

     apply plugin: 'com.hujiang.android-aspectjx'
***
    api 'org.aspectj:aspectjrt:1.8.13'

四.简单例子一:按钮两秒内不可再按
(1)声明注解类:

package aop
@Retention(AnnotationRetention.RUNTIME)
@Target(AnnotationTarget.FUNCTION)
annotation class AopOnclick (val value:Long = 2000){
}

(2)功能类:

package aop

import android.os.SystemClock
/*
两次间隔是否超过规定时间
 */
object AopClickUtil {
    private  var mLastClickTime:Long = 0
    fun isFastDoubleClick(intervalMillis:Long):Boolean{
        val time = SystemClock.elapsedRealtime()
        val tiemInterval = Math.abs(time- mLastClickTime)
        return if(tiemInterval<intervalMillis){
            true
        }else{
            mLastClickTime = time
            false
        }
    }
}

(3) 切面类:

@Aspect
class AopClickAspect{
    /*
        定义入口 @注解 访问权限 返回值类型 类名.函数名(参数)
     */
    @Pointcut("execution(@aop.AopOnclick * *(..))")
    fun methodAnnotated(){

    }
    @Around("methodAnnotated()")
    @Throws(Throwable::class)
    fun aroundJoinPoint(joinPoint: ProceedingJoinPoint){
        val methodSignature = joinPoint.signature as MethodSignature
        val method = methodSignature.method
        //判断此方法是否有AopOnclick注解
        if(!method.isAnnotationPresent(AopOnclick::class.java)){
            return
        }
        Log.d("aspect","method name:"+method.name)
        val aopOnclick = method.getAnnotation(AopOnclick::class.java)
        if(!AopClickUtil.isFastDoubleClick(aopOnclick.value)){
            joinPoint.proceed()
        }
    }
}

(4)使用

        login_ID.setOnClickListener(object :View.OnClickListener{
            @AopOnclick
            override fun onClick(v: View?) {
            //do something
            }

        })

五 权限控制框架例子。
(1)权限反馈接口

interface IPermission {
    fun onPermissionGranted()
    fun onPermissionDefied(requestCode:Int)
    fun onPermissionCanceled(requestCode: Int)
}

(2)注解类

@Retention(AnnotationRetention.RUNTIME)
@Target(AnnotationTarget.FUNCTION)
annotation class PermissionNeed( val permissions: Array<String>,val requestCode:Int = 0) {
}

(3)权限展示透明activity类

class PermissionActivity : Activity() {
    var mRequestCode:Int? = 0
    companion object{
        val PERMISSION:String = "permission"
        val REQUESTCODE:String = "requestCode"
        private var mIPermission:IPermission? = null
        fun startPermissionRequest(context: Context,permissions: Array<String>,requestCode:Int,iPermission: IPermission){
            mIPermission = iPermission
            var intent = Intent(context,PermissionActivity::class.java)
            intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK or  Intent.FLAG_ACTIVITY_CLEAR_TOP)
            var bundle = Bundle()
            bundle.putStringArray(PERMISSION,permissions)
            bundle.putInt(REQUESTCODE,requestCode)
            intent.putExtras(bundle)
            context.startActivity(intent)
            if(context is Activity){
                (context as Activity).overridePendingTransition(0,0)
            }
        }
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        var bundle = intent.extras
        var permissions = bundle?.getStringArray(PERMISSION)
        mRequestCode = bundle?.getInt(REQUESTCODE)
        requestPermission(permissions,mRequestCode)
    }

    private fun requestPermission(permissions: Array<String>?, requestCode: Int?) {
        /*
        权限通过
         */
        if(hasSelfPermission(permissions!!)){
              mIPermission?.onPermissionGranted()
              finish()
        } else{
            ActivityCompat.requestPermissions(this,permissions!!,requestCode!!)
            for (item in permissions){
                Log.d("permission",item+"\n")
            }
        }

    }

    override fun onRequestPermissionsResult(
        requestCode: Int,
        permissions: Array<out String>,
        grantResults: IntArray
    ) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults)
        if(mRequestCode==requestCode) {
            if (verifyPermission(grantResults)) {
                mIPermission?.onPermissionGranted()
            } else {
                if (shouldShoeRequestPermissionRationale(permissions!!)) {
                    mIPermission?.onPermissionCanceled(requestCode)
                    //
                } else {
                    mIPermission?.onPermissionDefied(requestCode)
                }

            }
           finish()
            overridePendingTransition(0, 0)
        }
    }

    fun hasSelfPermission(permissions: Array<String>):Boolean{
        for (item in permissions){
            if(ContextCompat.checkSelfPermission(this,item)!=PackageManager.PERMISSION_GRANTED){
                return  false
            }
        }
        return  true
    }

    fun verifyPermission(grantResults: IntArray):Boolean{
        if(grantResults.size==0) return false
        for(item in grantResults){
            if(item!=PackageManager.PERMISSION_GRANTED){
                return false
            }
        }
        return  true
    }
    fun shouldShoeRequestPermissionRationale(permissions: Array< out String>):Boolean {
        for(item in permissions){
            if(ActivityCompat.shouldShowRequestPermissionRationale(this,item)){
                return  true
            }
        }
        return  false
    }

}

注册:此activity

       <activity android:name="permission.PermissionActivity"
            android:theme="@style/translucent"
            />

style:

    <style name="translucent" parent="Theme.AppCompat.Light.NoActionBar">
        <item name="android:windowBackground">@android:color/transparent</item>
        <item name="android:windowIsTranslucent">true</item>
        <item name="android:windowAnimationStyle">@android:style/Animation.Translucent</item>
    </style>

(4)切面类


@Aspect
class PermissionAspect {
    @Pointcut("execution(@permission.PermissionNeed * *(..)) && @annotation(permissionNeed)")
    fun requestPermission(permissionNeed:PermissionNeed){}
    @Around("requestPermission(permissionNeed)")
    fun aroundJoinPoint(joinPoint: ProceedingJoinPoint,permissionNeed:PermissionNeed){
        var obj = joinPoint.`this`
        var context:Context = obj as Context

        PermissionActivity.startPermissionRequest(context,permissionNeed.permissions,
            permissionNeed.requestCode,object:IPermission{
                override fun onPermissionGranted() {
                    //通过了则调用对应被注解的方法
                    joinPoint.proceed()
                    Log.d("permission","Granted:")
                }

                override fun onPermissionDefied(requestCode: Int) {
                    Log.d("permission","defied:"+requestCode.toString())
                }

                override fun onPermissionCanceled(requestCode: Int) {
                    Log.d("permission","canceled:"+requestCode.toString())
                }

            })


    }

}

(5)调用:在所需的类中

    @PermissionNeed(permissions = arrayOf(
        Permission.WRITE_EXTERNAL_STORAGE
        , Permission.READ_PHONE_STATE
        ,android.Manifest.permission.ACCESS_NOTIFICATION_POLICY
        ,android.Manifest.permission.INTERNET
        ,android.Manifest.permission.ACCESS_WIFI_STATE
        ,android.Manifest.permission.ACCESS_NETWORK_STATE
        ,android.Manifest.permission.WRITE_EXTERNAL_STORAGE
    ),requestCode = 101)
    private fun requestBasePermission(){
     //do something
     
}

这样只要调用requestBasePermission()方法就会申请权限(如果没申请或者申请没有过),这里的权限拒绝和权限拒绝不再询问没有处理,可以自个加。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值