组件化知识梳理(4) - IOC & AOP 思想在 Arouter 中的应用

一、IoC

1.1 基本概念

IoC(Inversion of Control),中文翻译为 控制反转,具体实现是 由容器来控制业务对象之间的依赖关系,最终的目的是 避免和降低对象间的依赖关系。本质上是控制权由应用代码转到了外部容器,控制权的转移即是所谓的反转。

IoC的实现策略有两种:

  • 依赖查找:容器中的 受控对象 通过 容器API来查找自己所依赖的资源和协作对象。
  • 依赖注入(Dependency Injection):对象只提供普通的方法让容器去决定依赖关系,容器全权负责组件的装配,它会把符合依赖关系的对象通过属性或者是构造函数传递给需要的对象。优点是:
    • 查询依赖操作和应用代码分离
    • 受控对象不会使用到容器的特定API,这样我们的受控对象可以搬出容器单独使用。

1.2 IoC 在 Arouter 中的应用

在第一篇文章中,我们介绍了Arouter中依赖注入的使用方法。在调用模块中,使用下面的方法来启动 目标页面

@Route(path = RouterMap.HOME_FRAGMENT)
public class HomeFragment extends Fragment {

    private class HomeClickListener implements View.OnClickListener {

        @Override
        public void onClick(View v) {
            int id = v.getId();
            if (id == R.id.bt_no_result) {
               //...
            } else if (id == R.id.bt_inject) {
                SerialBean bean = new SerialBean();
                bean.setName("SerialBean");
                bean.setAge(18);
                ARouter.getInstance().build(RouterMap.INJECT_ACTIVITY)
                        .withInt(ConstantMap.INJECT_AGE, 18)
                        .withObject(ConstantMap.INJECT_OBJECT, bean)
                        .navigation();
            }
        }
    }
}

而在 目标页面 中,只需要使用@Autowired来声明对应的Key,就可以自动接收跳转过来的参数值,对被注解的成员变量进行赋值:

@Route(path = RouterMap.INJECT_ACTIVITY)
public class InjectActivity extends AppCompatActivity {

    @Autowired(name = ConstantMap.INJECT_AGE)
    int age;

    @Autowired(name = ConstantMap.INJECT_OBJECT)
    SerialBean bean;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        ARouter.getInstance().inject(this);
        Utils.toast(this, "age=" + age + ",bean.age=" + bean.getAge() + ",bean.name=" + bean.getName());
    }
}

在上面的代码中,和1.1中谈到的基础概念里面的对应关系为:

  • 受控对象 -> 使用@Autowired注解的变量。
  • 容器 -> 在编译期动态创建的InjectActivity$$ARouter$$Autowired 类。

关于依赖注入的原理,我们在 组件化知识梳理(2) - Arouter 源码分析之 Complier SDK 中已经分析过了 。编译期动态创建的注入类如下所示,InjectActivity不再去对成员变量进行赋值,而是由 外部容器 来提供具体的实现,这里的 外部容器 就是在编译期动态创建ISyringe的实现类。

public class InjectActivity$$ARouter$$Autowired implements ISyringe {
  private SerializationService serializationService;

  @Override
  public void inject(Object target) {
    serializationService = ARouter.getInstance().navigation(SerializationService.class);
    InjectActivity substitute = (InjectActivity)target;
    substitute.age = substitute.getIntent().getIntExtra("inject_age", substitute.age);
    if (null != serializationService) {
      substitute.bean = serializationService.parseObject(substitute.getIntent().getStringExtra("inject_object"), new com.alibaba.android.arouter.facade.model.TypeWrapper<SerialBean>(){}.getType());
    } else {
      Log.e("ARouter::", "You want automatic inject the field 'bean' in class 'InjectActivity' , then you should implement 'SerializationService' to support object auto inject!");
    }
  }
}

整个依赖注入的流程为:


依赖注入的流程

二、AOP

2.1 基本概念

AOP(Aspect Oriented Programming),中文翻译为 面向切面编程

AOP是对于OOP的一种补充,当我们采用OOP时,其目的就是为了将功能模块化,每个模块处理自己的事情。AOP就是为了将多模块当中 公用的功能 集中起来进行管理。

关于AOP的详细说明可以参考下面这篇文章:深入理解 Android 之 AOP

2.2 AOP 在 Arouter 中的应用

首先想一下,在以前,我们从一个Activity跳转到另一个Activity都是直接采用startActivity方式,而我们页面之间的跳转关系有可能是非常复杂的,像下面这样:

复杂的页面跳转关系

然后,突然有一天,产品来了,说要给页面2加上与账户有关的信息,当其它任意页面跳转到页面2之前需要判断是否登陆了,如果没登陆,那么就跳转到页面5,这时候我们有两种选择:

  • 在每个跳转页面2的地方都加上是否登陆的判断。
  • 在页面2被调起后再去判断,如果没登陆,那么自己再执行一步跳转到页面5的操作。

看起来方案2比较可行,但是其实就是稍微好一点,假如页面4有一天也要加入相同的逻辑,那么我们是不是就需要把页面2内的代码又拷贝一遍呢?

Arouter给出的解决方法,就是 拦截器

@Interceptor(priority = 1, name = "重新分组进行拦截")
public class BaseInterceptor implements IInterceptor {

    @Override
    public void process(Postcard postcard, InterceptorCallback callback) {
        if (postcard.getExtra() == ConstantMap.LOGIN_EXTRA) {
            boolean isLogin = postcard.getExtras().getBoolean(ConstantMap.IS_LOGIN);
            if (!isLogin) {
                ARouter.getInstance().build(RouterMap.INTER_MIDDLE_ACTIVITY).navigation();
                callback.onInterrupt(null);
            } else {
                postcard.withString(ConstantMap.IS_LOGIN_EXTRA, "登录了!");
                callback.onContinue(postcard);
            }
        } else {
            callback.onContinue(postcard);
        }
    }

    @Override
    public void init(Context context) {}

}

所有没有配置greenChannel()的页面跳转,都会按造优先级的顺序通过各拦截器的process方法。在@Route注解中配置extras属性,然后在拦截器当中通过postcard.getExtra()进行识别,我们就可以区分目标页面的类型,根据它来判断跳转目标页面所需的条件,从而达到对于页面跳转的统一管理。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,847评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,208评论 1 292
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,587评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,942评论 0 205
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,332评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,587评论 1 218
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,853评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,568评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,273评论 1 242
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,542评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,033评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,373评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,031评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,073评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,830评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,628评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,537评论 2 269

推荐阅读更多精彩内容

  • 什么是Spring Spring是一个开源的Java EE开发框架。Spring框架的核心功能可以应用在任何Jav...
    jemmm阅读 16,360评论 1 133
  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 170,568评论 25 707
  • 今天周六,照惯例跟老公带着儿子去他姥姥家玩,只不过因为他咳嗽就加了做雾化治疗的行程。 中午单位电话通知开会,一看时...
    油油的悠悠阅读 143评论 0 0
  • 郭靖抱着梅超风,和沙通天等人斗武。黄蓉想出了一个妙计,得以让郭靖脱身。 沙通天等人接到完颜洪烈的命令,去寻找包惜弱...
    鲁丹洋阅读 633评论 0 0
  • 冰与火(二首) 杨桂晔 零度窗花 别以 阳光的手 探视我 零度窗花 我是冬天 美丽的 零度窗花 在冷之下 克服冷 ...
    斑斓月阅读 297评论 0 1