<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      安卓筆記俠

      專(zhuān)注安卓開(kāi)發(fā)

      導(dǎo)航

      AOP面向切面編程在Android中的使用

      GitHub地址(歡迎下載完整Demo)

      https://github.com/ganchuanpu/AOPDemo

      項(xiàng)目需求描述

      個(gè)人中心.jpg

      我想類(lèi)似于這樣的個(gè)人中心的界面,大家都不會(huì)陌生吧。那幾個(gè)有箭頭的地方都是可以點(diǎn)擊進(jìn)行頁(yè)面跳轉(zhuǎn)的,但是需要先判斷用戶(hù)是否登錄,如果已經(jīng)登錄,則正常跳轉(zhuǎn),如果沒(méi)有登錄,則跳轉(zhuǎn)到登錄頁(yè)面先登錄,但凡是有注冊(cè),登錄的APP,這樣的操作,大家應(yīng)該都很熟悉吧。一般情況下,我們的邏輯是這樣的…

      /**
        * 跳轉(zhuǎn)到我的關(guān)注頁(yè)面
      */
      public void toMyAttention() {
           // 判斷當(dāng)前用戶(hù)是否登錄
           if(LoginHelper.isLogin(this)) {
               // 如果登錄才跳轉(zhuǎn),進(jìn)入我的關(guān)注頁(yè)面
               Intent intent = new Intent(this, WaitReceivingActivity.class);
               startActivity(intent);
           }else{
             //跳轉(zhuǎn)到登錄頁(yè)面,先登錄
               Intent intent = new Intent(this, LoginActivity.class);
               startActivity(intent);
           }
      }

      重復(fù)的體力勞動(dòng),想想都可怕。而且類(lèi)似的還有網(wǎng)絡(luò)判斷,權(quán)限管理,Log日志的統(tǒng)一管理這樣的問(wèn)題。那么,我們也沒(méi)有更優(yōu)雅的方式來(lái)解決這一類(lèi)的問(wèn)題呢,答案是有的。

      先給出我解決了上述問(wèn)題之后的代碼

      /**
          *  跳轉(zhuǎn)到我的關(guān)注頁(yè)面
          */
          @CheckLogin
          public void toMyAttention() {
               Intent intent = new Intent(this, WaitReceivingActivity.class);
               startActivity(intent);
          }

      AspectJ

      AspectJ實(shí)際上是對(duì)AOP編程思想的一個(gè)實(shí)踐,AOP雖然是一種思想,但就好像OOP中的Java一樣,一些先行者也開(kāi)發(fā)了一套語(yǔ)言來(lái)支持AOP。目前用得比較火的就是AspectJ了,它是一種幾乎和Java完全一樣的語(yǔ)言,而且完全兼容Java(AspectJ應(yīng)該就是一種擴(kuò)展Java,但它不是像Groovy那樣的拓展。)。當(dāng)然,除了使用AspectJ特殊的語(yǔ)言外,AspectJ還支持原生的Java,只要加上對(duì)應(yīng)的AspectJ注解就好。所以,使用AspectJ有兩種方法:
      - 完全使用AspectJ的語(yǔ)言。這語(yǔ)言一點(diǎn)也不難,和Java幾乎一樣,也能在AspectJ中調(diào)用Java的任何類(lèi)庫(kù)。AspectJ只是多了一些關(guān)鍵詞罷了。
      - 或者使用純Java語(yǔ)言開(kāi)發(fā),然后使用AspectJ注解,簡(jiǎn)稱(chēng)@AspectJ

      基礎(chǔ)概念
      - Aspect 切面:切面是切入點(diǎn)和通知的集合。

      • PointCut 切入點(diǎn):切入點(diǎn)是指那些通過(guò)使用一些特定的表達(dá)式過(guò)濾出來(lái)的想要切入Advice的連接點(diǎn)。

      • Advice 通知:通知是向切點(diǎn)中注入的代碼實(shí)現(xiàn)方法。

      • Joint Point 連接點(diǎn):所有的目標(biāo)方法都是連接點(diǎn).

      • Weaving 編織:主要是在編譯期使用AJC將切面的代碼注入到目標(biāo)中, 并生成出代碼混合過(guò)的.class的過(guò)程.

      實(shí)踐步驟

      1、在android studio中直接配置AspectJ,這個(gè)配置很重要,如果失敗,后面就無(wú)法成功,先貼出我的配置,在app的build.gradle中做如下配置

       1 apply plugin: 'com.android.application'
       2 import org.aspectj.bridge.IMessage
       3 import org.aspectj.bridge.MessageHandler
       4 import org.aspectj.tools.ajc.Main
       5 
       6 buildscript {
       7     repositories {
       8         mavenCentral()
       9     }
      10     dependencies {
      11         classpath 'org.aspectj:aspectjtools:1.8.9'
      12         classpath 'org.aspectj:aspectjweaver:1.8.9'
      13     }
      14 }
      15 repositories {
      16     mavenCentral()
      17 }
      18 final def log = project.logger
      19 final def variants = project.android.applicationVariants
      20 variants.all { variant ->
      21     if (!variant.buildType.isDebuggable()) {
      22         log.debug("Skipping non-debuggable build type '${variant.buildType.name}'.")
      23         return;
      24     }
      25 
      26     JavaCompile javaCompile = variant.javaCompile
      27     javaCompile.doLast {
      28         String[] args = ["-showWeaveInfo",
      29                          "-1.8",
      30                          "-inpath", javaCompile.destinationDir.toString(),
      31                          "-aspectpath", javaCompile.classpath.asPath,
      32                          "-d", javaCompile.destinationDir.toString(),
      33                          "-classpath", javaCompile.classpath.asPath,
      34                          "-bootclasspath", project.android.bootClasspath.join(File.pathSeparator)]
      35         log.debug "ajc args: " + Arrays.toString(args)
      36 
      37         MessageHandler handler = new MessageHandler(true);
      38         new Main().run(args, handler);
      39         for (IMessage message : handler.getMessages(null, true)) {
      40             switch (message.getKind()) {
      41                 case IMessage.ABORT:
      42                 case IMessage.ERROR:
      43                 case IMessage.FAIL:
      44                     log.error message.message, message.thrown
      45                     break;
      46                 case IMessage.WARNING:
      47                     log.warn message.message, message.thrown
      48                     break;
      49                 case IMessage.INFO:
      50                     log.info message.message, message.thrown
      51                     break;
      52                 case IMessage.DEBUG:
      53                     log.debug message.message, message.thrown
      54                     break;
      55             }
      56         }
      57     }
      58 }
      59 
      60 android {
      61     compileSdkVersion 25
      62     buildToolsVersion "25.0.2"
      63     defaultConfig {
      64         applicationId "com.zx.aopdemo"
      65         minSdkVersion 17
      66         targetSdkVersion 25
      67         versionCode 1
      68         versionName "1.0"
      69         testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
      70     }
      71     buildTypes {
      72         release {
      73             minifyEnabled false
      74             proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
      75         }
      76     }
      77 }
      78 
      79 dependencies {
      80     compile fileTree(dir: 'libs', include: ['*.jar'])
      81     androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
      82         exclude group: 'com.android.support', module: 'support-annotations'
      83     })
      84     compile 'com.android.support:appcompat-v7:25.3.1'
      85     compile 'com.android.support.constraint:constraint-layout:1.0.2'
      86     compile 'org.aspectj:aspectjrt:1.8.9'
      87     testCompile 'junit:junit:4.12'
      88 }

      為什么這么配置?因?yàn)锳spectJ是對(duì)java的擴(kuò)展,而且是完全兼容java的。但是編譯時(shí)得用Aspect專(zhuān)門(mén)的編譯器,這里的配置就是使用Aspect的編譯器,單獨(dú)加入aspectj依賴(lài)是不行的。到這里準(zhǔn)備工作已完成,可以開(kāi)始看看具體實(shí)現(xiàn)了。

      2、創(chuàng)建切面AspectJ
      用來(lái)處理觸發(fā)切面的回調(diào)

       1 @Aspect
       2 public class CheckLoginAspectJ {
       3     private static final String TAG = "CheckLogin";
       4 
       5     /**
       6      * 找到處理的切點(diǎn)
       7      * * *(..)  可以處理CheckLogin這個(gè)類(lèi)所有的方法
       8      */
       9     @Pointcut("execution(@com.zx.aopdemo.login.CheckLogin  * *(..))")
      10     public void executionCheckLogin() {
      11     }
      12 
      13     /**
      14      * 處理切面
      15      *
      16      * @param joinPoint
      17      * @return
      18      */
      19     @Around("executionCheckLogin()")
      20     public Object checkLogin(ProceedingJoinPoint joinPoint) throws Throwable {
      21         Log.i(TAG, "checkLogin: ");
      22         MethodSignature signature = (MethodSignature) joinPoint.getSignature();
      23         CheckLogin checkLogin = signature.getMethod().getAnnotation(CheckLogin.class);
      24         if (checkLogin != null) {
      25             Context context = (Context) joinPoint.getThis();
      26             if (MyApplication.isLogin) {
      27                 Log.i(TAG, "checkLogin: 登錄成功 ");
      28                 return joinPoint.proceed();
      29             } else {
      30                 Log.i(TAG, "checkLogin: 請(qǐng)登錄");
      31                 Toast.makeText(context, "請(qǐng)登錄", Toast.LENGTH_SHORT).show();
      32                 return null;
      33             }
      34         }
      35         return joinPoint.proceed();
      36     }
      37 }

      這里要使用Aspect的編譯器編譯必須給類(lèi)打上標(biāo)注,@Aspect。
      還有這里的Pointcut注解,就是切點(diǎn),即觸發(fā)該類(lèi)的條件。里面的字符串如下

      AspectJ中的Join Point.png

      在Pointcut這里,我使用了execution,也就是以方法執(zhí)行時(shí)為切點(diǎn),觸發(fā)Aspect類(lèi)。而execution里面的字符串是觸發(fā)條件,也是具體的切點(diǎn)。我來(lái)解釋一下參數(shù)的構(gòu)成。“execution(@com.zx.aopdemo.login.CheckLogin * *(..))”這個(gè)條件是所有加了CheckLogin注解的方法或?qū)傩远紩?huì)是切點(diǎn),范圍比較廣。

      • **:表示是任意包名
      • ..:表示任意類(lèi)型任意多個(gè)參數(shù)

      “com.zx.aopdemo.login.CheckLogin”這是我的項(xiàng)目包名下需要指定類(lèi)的絕對(duì)路徑。再來(lái)看看@Around,Around是指JPoint執(zhí)行前或執(zhí)行后被觸發(fā),除了Around還有其他幾種方式。

      創(chuàng)建完Aspect類(lèi)之后,還需要一個(gè)注解類(lèi),它的作用是:哪里需要做切點(diǎn),那么哪里就用注解標(biāo)注一下,這樣方便快捷。

      3、創(chuàng)建注解類(lèi)

      package com.zx.aopdemo.login;
      
      import java.lang.annotation.ElementType;
      import java.lang.annotation.Retention;
      import java.lang.annotation.RetentionPolicy;
      import java.lang.annotation.Target;
      
      @Target(ElementType.METHOD) //可以注解在方法 上
      @Retention(RetentionPolicy.RUNTIME) //運(yùn)行時(shí)(執(zhí)行時(shí))存在
      public @interface CheckLogin {
      }

      4、Activity使用登錄的注解

      public class LoginActivity extends AppCompatActivity implements View.OnClickListener, RadioGroup.OnCheckedChangeListener {
      
          private RadioGroup radioGroup;
      
          @Override
          protected void onCreate(Bundle savedInstanceState) {
              super.onCreate(savedInstanceState);
              setContentView(R.layout.activity_login);
      
             test();
          }
      
          @CheckLogin
         public void test(){  
              Log.i("tag","判斷是否登錄");  
          }  

      test()方法執(zhí)行時(shí)就是一個(gè)切點(diǎn)。在執(zhí)行test()時(shí),會(huì)回調(diào)上面的CheckLoginAspectJ類(lèi)的executionCheckLogin()方法。然后會(huì)執(zhí)行
      如下方法

       1 /**
       2      * 處理切面
       3      *
       4      * @param joinPoint
       5      * @return
       6      */
       7     @Around("executionCheckLogin()")
       8     public Object checkLogin(ProceedingJoinPoint joinPoint) throws Throwable {
       9         Log.i(TAG, "checkLogin: ");
      10         MethodSignature signature = (MethodSignature) joinPoint.getSignature();
      11         CheckLogin checkLogin = signature.getMethod().getAnnotation(CheckLogin.class);
      12         if (checkLogin != null) {
      13             Context context = (Context) joinPoint.getThis();
      14             if (MyApplication.isLogin) {
      15                 Log.i(TAG, "checkLogin: 登錄成功 ");
      16                 return joinPoint.proceed();
      17             } else {
      18                 Log.i(TAG, "checkLogin: 請(qǐng)登錄");
      19                 Toast.makeText(context, "請(qǐng)登錄", Toast.LENGTH_SHORT).show();
      20                 return null;
      21             }
      22         }
      23         return joinPoint.proceed();
      24     }

      如果使用的是以方法相關(guān)為切點(diǎn),那么使用MethodSignature來(lái)接收joinPoint的Signature。如果是屬性或其他的,那么可以使用Signature類(lèi)來(lái)接收。之后可以使用Signature來(lái)獲取注解類(lèi)。,那么通過(guò)jointPoint.getThis()獲取使用該注解的的上下文對(duì)象

       

      https://www.jianshu.com/p/f4e8760e6984

      posted on 2018-03-18 11:58  安卓筆記俠  閱讀(6398)  評(píng)論(0)    收藏  舉報(bào)

      主站蜘蛛池模板: 微拍福利一区二区三区| 国产视频一区二区在线看| 国产毛片精品av一区二区| 边摸边吃奶边做爽动态 | 亚洲AV无码国产成人久久强迫| 成人午夜av在线播放| 免费十八禁一区二区三区| 中文文字幕文字幕亚洲色| 人妻一本久道久久综合鬼色| 大荔县| 欧美大bbbb流白水| 国内外精品激情刺激在线| 久久被窝亚洲精品爽爽爽| 亚洲精品欧美综合二区| 亚洲欧洲一区二区精品| 国产精成人品日日拍夜夜| 四虎精品免费永久免费视频| 久久国内精品一区二区三区| 深夜精品免费在线观看| 怀安县| 国产精品va无码一区二区| 欧美人与动欧交视频| 又粗又硬又黄a级毛片| 亚洲 成人 无码 在线观看| 波多野结衣视频一区二区| 高清自拍亚洲精品二区| 91亚洲国产成人久久精| 狠狠色综合久久狠狠色综合| 中文无码热在线视频| 国产精品国产高清国产一区| 三上悠亚精品一区二区久久| 人妻伦理在线一二三区| 一区二区三区精品视频免费播放| 少妇伦子伦精品无吗| 日韩加勒比一本无码精品| 又黄又无遮挡AAAAA毛片| 天天躁夜夜躁av天天爽| 图片区 小说区 区 亚洲五月 | 国产一区二区高清不卡| 成av免费大片黄在线观看| 国产福利深夜在线播放|