开源项目源码解析

组件化知识梳理(4) - IOC & AOP 思想在 A

2018-05-08  本文已影响181人  泽毛

一、IoC

1.1 基本概念

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

IoC的实现策略有两种:

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中谈到的基础概念里面的对应关系为:

关于依赖注入的原理,我们在 组件化知识梳理(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比较可行,但是其实就是稍微好一点,假如页面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()进行识别,我们就可以区分目标页面的类型,根据它来判断跳转目标页面所需的条件,从而达到对于页面跳转的统一管理。

上一篇下一篇

猜你喜欢

热点阅读