美文网首页AndroidAndroid开发AOP
AOP面向切面编程 - 淘宝京东网络处理

AOP面向切面编程 - 淘宝京东网络处理

作者: 红橙Darren | 来源:发表于2017-08-28 21:15 被阅读4895次

现象描述

当我们打开京东 app 进入首页,如果当前是没有网络的状态,里面的按钮点击是没有反应的。只有当我们打开网络的情况下,点击按钮才能跳转页面,按照我们一般人写代码的逻辑应该是这个样子:

     /**
     * 跳转到待收货页面
     */
    public void jumpWaitReceiving() {
        // 判断当前有没有网络
        if(CheckNetUtil.isNetworkAvailable(this)) {
            // 当前有网络我才跳转,进入待收货页面
            Intent intent = new Intent(this, WaitReceivingActivity.class);
            startActivity(intent);
        }
    }

    /**
     * 跳转到我的钱包页面
     */
    public void jumpMineWallet() {
        if(CheckNetUtil.isNetworkAvailable(this)) {
            Intent intent = new Intent(this, MineWalletActivity.class);
            startActivity(intent);
        }
    }

上面这段代码看似没有任何问题,完全满足京东的网络处理需求,就写一个 if(有网) 跳转到下一个页面,没网就不做任何处理。但是真的没有问题吗? 按照京东的页面,这些 if() 代码估计要写上几十次,而且有些在 Activity,有些甚至在 Fragment 中,很难管理。如果有一天需求变动,我们估计要改动多处。我们到底有没有更好的方式,且接着往下看。

面向切面

我们现在想做的其实就是,我根本不想写那么多的 if() 代码,而且写得越多越不好管理,比如有一天没网络要弹 Toast ,那么岂不是很多地方要去改动。所以接下来,我们打算采用面向切面的编程思想,把网络检测切出来统一管理。第一,保证代码的简洁性,第二,需求有变动时我们只需要统一改动那一部分代码,第三,有很多这里不一一列出来了。

那么什么是 AOP ? 好处又有什么?

面向切面(AOP)其实就是把众多方法中的所有共有代码全部抽取出来,放置到某个地方集中管理,然后在具体运行时,再由容器动态织入这些共有代码的话,最起码可以解决两个问题:

1.1 Android程序员在编写具体的业务逻辑处理方法时,只需关心核心的业务逻辑处理,既提高了工作效率,又使代码变更简洁优雅。
1.2 在日后的维护中由于业务逻辑代码与共有代码分开存放,而且共有代码是集中存放的,因此使维护工作变得简单轻松。

那到底应该怎么写呢? 请看我最终的代码,代码如下:

    /**
    * 跳转到待收货页面
    */
    @CheckNet
    public void jumpWaitReceiving() {
        Intent intent = new Intent(this, WaitReceivingActivity.class);
        startActivity(intent);
    }

    /**
     * 跳转到我的钱包页面
     */
    @CheckNet
    public void jumpMineWallet() {
        Intent intent = new Intent(this, MineWalletActivity.class);
        startActivity(intent);
    }

上面这段代码,也没看到你省了多少代码。但其实在我们真正的开发过程中,远不止检测网络这么个功能,比如还需要检测登录,需要上传日志,统计用户行为等等。这样,我们方法越多省的代码就会越多,而且所有的代码都统一进行了管理,后面维护起来也方便,况且跟最开始比起来,代码的确也变得更加简洁了。那好吧,我们就只看到加了一个 CheckNet ,也没看到你判断网络的代码啊?别急,且接着往下看。最主要的其实还是下面这段代码:

/**
 * Created by hcDarren on 2017/8/27.
 * 处理网络检测切面
 */
@Aspect
public class SectionAspect {

    /**
     * 找到处理的切点
     * * *(..)  可以处理所有的方法
     */
    @Pointcut("execution(@com.darren.architect_day02.CheckNet * *(..))")
    public void checkNetBehavior() {

    }

    /**
     * 处理切面
     */
    @Around("checkNetBehavior()")
    public Object checkNet(ProceedingJoinPoint joinPoint) throws Throwable {
        Log.e("TAG", "checkNet");
        // 做埋点  日志上传  权限检测(我写的,RxPermission , easyPermission) 网络检测
        // 网络检测
        // 1.获取 CheckNet 注解  NDK  图片压缩  C++ 调用Java 方法
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        CheckNet checkNet = signature.getMethod().getAnnotation(CheckNet.class);
        if (checkNet != null) {
            // 2.判断有没有网络  怎么样获取 context?
            Object object = joinPoint.getThis();// View Activity Fragment ; getThis() 当前切点方法所在的类
            Context context = getContext(object);
            if (context != null) {
                if (!isNetworkAvailable(context)) {
                    // 3.没有网络不要往下执行
                    Toast.makeText(context,"请检查您的网络",Toast.LENGTH_LONG).show();
                    return null;
                }
            }
        }
        return joinPoint.proceed();
    }

    /**
     * 通过对象获取上下文
     *
     * @param object
     * @return
     */
    private Context getContext(Object object) {
        if (object instanceof Activity) {
            return (Activity) object;
        } else if (object instanceof Fragment) {
            Fragment fragment = (Fragment) object;
            return fragment.getActivity();
        } else if (object instanceof View) {
            View view = (View) object;
            return view.getContext();
        }
        return null;
    }

    /**
     * 检查当前网络是否可用
     *
     * @return
     */
    private static boolean isNetworkAvailable(Context context) {
        // 获取手机所有连接管理对象(包括对wi-fi,net等连接的管理)
        ConnectivityManager connectivityManager = (ConnectivityManager)
                context.getSystemService(Context.CONNECTIVITY_SERVICE);
        if (connectivityManager != null) {
            // 获取NetworkInfo对象
            NetworkInfo[] networkInfo = connectivityManager.getAllNetworkInfo();

            if (networkInfo != null && networkInfo.length > 0) {
                for (int i = 0; i < networkInfo.length; i++) {
                    // 判断当前网络状态是否为连接状态
                    if (networkInfo[i].getState() == NetworkInfo.State.CONNECTED) {
                        return true;
                    }
                }
            }
        }
        return false;
    }
}

今天的这期只是带大家写了一个开发中的小事例,我们有时要学会从面向对象的思想中切换过来,切换成我们的面向切面(AOP)的思想。如果注解不是特别了解,我会在接下来的几期文章中做一个充分的讲解。最后祝大家七夕节快乐,作为屌丝我,只能选择在家默默的写写文章。

所有分享大纲:Android进阶之旅 - 系统架构篇

视频讲解地址:http://pan.baidu.com/s/1ge4uT4R

相关文章

网友评论

  • markRao:aspectJ是啥?求解,谢谢
  • 274e07e81c4a:够了,有思路就够了,虽然没用过aspect,不过还是知道来干嘛的。之前就一直想怎么做这种全局的状态检测拦截,
  • 小無懶:别以为喝了几瓶雪花,谁都可以勇闯天涯。
    1024a21fd2cb:这么轴呢....
  • 冉桓彬:CheckNet这个类是啥啊?
    红橙Darren:@冉桓彬 就打了一个标记,结合这行代码 @Pointcut("execution(@com.darren.architect_day02.CheckNet * *(..))") 试试,反编译看看 class 变成什么样就知道了:smile: 也不用太纠结
  • 小無懶:你确定京东淘宝是这么做的? 人家对性能是有要求的。这做虽然方便,但是性能却不是很好!
    小無懶:@红橙Darren AOP 不耗性能?看来你真的不懂。
    红橙Darren:@小無懶 这是不耗性能的,网上千篇一律的注解耗性能,关键还是要自己了解原理。:smile: :smile:
    红橙Darren:@小無懶 我可没这么说,只是提供一种aop的思想,代码怎样其实不是太重要
  • 7d58a8dbe725:怎么打赏不了
  • 7d58a8dbe725:注解不是很理解,还希望大神可以解释一下
    红橙Darren:@Aspect 和 @Around 这些其实就是套路,主要是给 aspectJ 看的,如果是注解不是很理解可以看看其他文章
  • AWeiLoveAndroid:膜拜大佬
  • 橘子周二:thanks for you share,i be try to use👍
    橘子周二: @Mrz_7866 😂保底20分。现在是学一点用一点😁,被骂就有机会进步
    c9369af87744:@_RANGO 高考英语肯定没及格
  • 香脆的大鸡排:红橙哥,我觉得这篇文章可以再详细点更好了。虽然给出了关键代码。但是aspectjrt 并不能直接在android-studio中使用。需要编译时运行插件。我没有去下载下面的视频看,不知道里面有没有讲。比如:classpath配置之类的。 有些新手没有用过不排除他们依葫芦画瓢,不明白原理结果照着代码写了,运行没有任何结果。其实就是缺少编译时埋点的桩代码。
    光脚的呱牛:@红橙Darren 1.如果写教程就该把读者当成傻的 要说清楚所有的步骤 或者直接标注环境不做说明 2.看了代码其实就是这些注解类不了解,具体的逻辑代码是很简单的 只能说编译把麻烦的地方解决了 3.有些安卓开发的java基础差到爆,不是每个人起点都高 不过很想知道这些人是怎么混日子的
    红橙Darren: @香脆的大鸡排 我以为大家应该都会😃,我记得学java基础应该就要会了的😬
    香脆的大鸡排:有需要的小伙伴,看看这个吧。
    https://fernandocejas.com/2014/08/03/aspect-oriented-programming-in-android/
  • honglei92:Darren出品,必属精品
  • fancl:代码地址有吗
  • AJI大侠:作为屌丝的我看完后感觉好爽:sunglasses:
  • 1024a21fd2cb:好人一生平安~:ghost: 扎心不,老铁~
  • MISSGY_:辛苦了,每期都出视频
  • 小小混世魔王:作为屌丝的我只能在家默默的看看文章 :unamused:
    红橙Darren: @01b20568e3a6 😁😁😁
  • etrnel:🐶🐶🐶。节日快乐

本文标题:AOP面向切面编程 - 淘宝京东网络处理

本文链接:https://www.haomeiwen.com/subject/suzgdxtx.html