企业级app组件化开发5----Arouter路由

在之前的组件化开发中,如果ModuleA想要调用另一个ModuleB中的类或者方法,只能通过添加依赖的方式,而且是强依赖;这种形式存在的一个问题就是:如果ModuleB中的类发生改变,那么ModuleA也需要改变该类,甚至该类已经无法继续使用了,扩展性不强,耦合性太高。

在这里插入图片描述

但是开源的ARouter路由就解决了这个问题,Module之间不再是处于强耦合的关系,而是使用ARouter作为中间人,所有的Module在ARouter中注册后,那么其他的Module都可以调用ARouter中该Module的类和方法,而且Module在ARouter中注册之后,不管Module中怎么改变,其他获取到仍然是之前的类,不会因为其他的Module改变而需要去改变。

例如Module在ARouter注册一个类 B.a,ModuleA调用这个类,ModuleB此后将B.a改成了B.c,那么其他Module调用的依然是B.a,并不受ModuleB改变受到影响。

1、ARouter的基础使用

《阿里巴巴ARouter手册》具体使用可以从这里获取更多,还有源码解析等,这里主要讲解ARouter的主要用法。

(1)依赖配置

defaultConfig以及dependencies中添加以下依赖

javaCompileOptions {
            annotationProcessorOptions {
                arguments = [moduleName: project.getName()]
            }
        }
implementation 'com.alibaba:arouter-api:1.3.1'
annotationProcessor 'com.alibaba:arouter-compiler:1.1.3'

(2)Activity之间的跳转

在之前没有使用ARouter的时候,使用Activity之间跳转的方式是通过startActivity的方式,尤其是使用显示意图Intent跳转的时候,耦合性太高。

在使用ARouter时,首先需要在Application中注册初始化之后,才可以使用

 //初始化ARouter
        if(isDebug()){
            ARouter.openLog();
            ARouter.openDebug();
        }
        ARouter.init(this);

现在就可以实现Activity之间的跳转了,在当前Activity中,如果想要跳转到目标Activity,只需要以下一行代码即可。

 btn_jump.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                ARouter.getInstance().build(Router.MAIN_ACTIVITY).navigation();
            }
        });

build中,代表跳转的目标Activity,所以在目标Activity中,需要使用@Route注解来注释。

@Route(path = Router.MAIN_ACTIVITY)
public class MainActivity extends AppCompatActivity {

    private Handler handler = new Handler();
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        //注入
        ARouter.getInstance().inject(this);
    }
}

一旦使用注解,那么就需要将ARouter注入!!!

(3)Activity携带参数跳转

在ARouter提供的API中,可传递的数据类型和Intent基本一致:基本数据类型、可序列化数据(2种)。。。

ARouter.getInstance()
       .build(Router.MAIN_ACTIVITY)
       .withString("name","ClearLove")
       .withInt("age",12)
       .navigation();

目标Activity:

@Route(path = Router.MAIN_ACTIVITY)
public class MainActivity extends AppCompatActivity {

    private TextView tv_name,tv_age;
    @Autowired(name = "name") //这里可以不用写,因为携带的key是一致的
    String name;  // String mName;  如果这样声明就需要加name
    @Autowired()
    int age;


    private Handler handler = new Handler();
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        //注入
        ARouter.getInstance().inject(this);
        
        tv_name = findViewById(R.id.tv_name);
        tv_age = findViewById(R.id.tv_age);

        tv_name.setText(name);
        tv_age.setText(age+"");
    }
}

通过@Autowired注解来修饰,需要注意的是,如果携带数据的key一致,在@Autowired不需要声明name。

(4)Uri跳转

     Uri uri = Uri.parse(Router.MAIN_ACTIVITY);
                ARouter.getInstance()
                        .build(uri)
                        .withString("name","ClearLove")
                        .withInt("age",12)
                        .navigation();

(5)动画

   Uri uri = Uri.parse(Router.MAIN_ACTIVITY);
                ARouter.getInstance()
                        .build(uri)
                        .withTransition(Animation.REVERSE,Animation.ZORDER_TOP)
                        .withString("name","ClearLove")
                        .withInt("age",12)
                        .navigation();

使用withTransition可以设置入场动画和出场动画,来设置跳转动画。

(6)路由回调 NavigationCallback

 				 ARouter.getInstance()
                        .build(uri)
                        .withTransition(Animation.REVERSE,Animation.ZORDER_TOP)
                        .withString("name","ClearLove")
                        .withInt("age",12)
                        .navigation(VideoActivity.this, new NavigationCallback() {
                            @Override
                            public void onFound(Postcard postcard) {
                                Log.e("TAG",postcard.getPath()+","+postcard.getGroup());
                            }

                            @Override
                            public void onLost(Postcard postcard) {

                            }

                            @Override
                            public void onArrival(Postcard postcard) {

                            }

                            @Override
                            public void onInterrupt(Postcard postcard) {

                            }
                        });

使用NavigationCallback可以完成对路由的回调,主要分为4个方面,分别为onFound(路由寻址成功)、onLost(路由寻址失败)、onArrival(路由导航成功)、onInterrupt(拦截器),在四个方法中,都涉及到了一个类Postcard ,有两个比较关键的属性值,分别是path和group,path指的是路由的路径,group指的是分组。

2020-05-31 17:37:06.335 29646-29646/com.example.glide E/TAG: /app/main_activity,app

默认情况下,group的分组为app,也就是二级目录/xx/xxx,第一个位置的数据。

在navigation中除了可以完成路由的回调,还可以完成带结果的回调,也就是startActivityForResult,可以传入requestCode来实现。

2、ARouter实现服务化

以上只是ARouter使用的一些常用方法,最关键的还是在组件化开发中,避免模块间的强依赖,使用ARouter服务化进行模块解耦,才是组件化中的核心。

下面拉回开篇的场景:有两个ModuleA和ModuleB,ModuleA需要使用ModuleB中的一个类,如果相互依赖组件,本来没有关系的两个组件变得耦合性太高;所以对于业务层的抽离,可以在lib_base组件中,创建一个服务接口,该接口可以对外暴露;该接口的具体实现类是在ModuleB中实现的,具体的实现就是ModuleA想要调用ModuleB中的部分方法;那么当ModuleA想要调用ModuleB中类的方法时,直接依赖lib_base组件,通过ARouter路由获取,这样通过lib_base组件将两个不相干的组件联系起来。

当前存在lib_video lib_base lib_share三个组件,lib_share想要调用lib_video中的方法,那么首先在lib_base中创建一个接口,继承自IProvider。

public interface VideoService extends IProvider {

    String getVideoName();
}

lib_video:

lib_video需要依赖lib_base库,完成VideoService 的具体实现

@Route(path = "/lib_video/video_service")
public class VideoServiceImpl implements VideoService {

    @Override
    public String getVideoName() {

        Video video = new Video("唐人街探案",3);
        return video.getVideoName();
    }

    @Override
    public void init(Context context) {

    }
}

lib_share:

lib_share同样需要依赖lib_base库,而不需要和lib_video库依赖。

	@Autowired(name = "/lib_video/video_service")
    VideoService mVideoService;

    private ShareSDKManager(){
        ARouter.getInstance().inject(this);
    }
    private static ShareSDKManager manager;
    public static ShareSDKManager getInstance(){
        if(manager == null){
            synchronized (ShareSDKManager.class){
                if(manager == null){
                    manager = new ShareSDKManager();
                }
            }
        }
        return manager;
    }
    
    //分享需要2类数据,参数和平台
    public void shareData(ShareData data,PlatformShareDataListener listener){
        this.listener = listener;

		/*省略部分代码*/
		
        String videoName = mVideoService.getVideoName();
        Log.e("TAG","name=="+videoName);
    }

组件路由服务化用法1:声明服务注意要加上路由地址,否则找不到该实现类,通过服务接口直接调用方法实现。

方法2:通过navigation导航

//不需要再加AutoWried注解
VideoService mVideoService2;

mVideoService2 = ARouter.getInstance().navigation(VideoService.class);
        String videoName = mVideoService2.getVideoName();

方法3:通过build导航

//不需要再加AutoWried注解
VideoService mVideoService2;

mVideoService2 = (VideoService) ARouter.getInstance().build("/lib_video/video_service").navigation();
        String videoName = mVideoService2.getVideoName();

3、ARouter分组与拦截器

ARouter拦截器,有些类似于之前在OkHttp组件开发中,讲到的拦截器。ARouter拦截器主要是拦截事件跳转,先看下代码

@Interceptor(priority = 1,name = "login_interceptor")
public class LoginInterceptor implements IInterceptor {

    @Override
    public void process(Postcard postcard, InterceptorCallback callback) {
        if(postcard.getGroup() == Router.NEED_LOGIN){
            //如果是需要登录分组
            ARouter.getInstance().build(Router.LOGIN_ACTIVITY).navigation();
        }else{
            callback.onContinue(postcard);
        }
    }

    @Override
    public void init(Context context) {

    }
}

这是一个与登录相关的拦截器,核心在于process,在process方法中有两个形参,分别是Postcard 和 InterceptorCallback 。

Postcard 在之前介绍过,包含路由地址和分组Group,分组Group是可以在Route注解中声明的,在路由导航的时候,可以在build中添加分组信息。

@Route(path = Router.MAIN_ACTIVITY,group = Router.NEED_LOGIN)
public class MainActivity extends AppCompatActivity {
ARouter.getInstance()
		//         路由地址             分组
       .build(Router.MAIN_ACTIVITY,Router.NEED_LOGIN)

当然加了分组之后,就可以通过拦截器,通过Postcard来获取路由地址的分组,如果获取到需要分组的信息,那么就需要判断登录信息是否过期(这里没有做这个操作,在实际开发中是需要做的),如果没有过期,那么就通过InterceptorCallback执行onContinue继续路由到对应地址,如果登录信息过期,那么就需要路由到登录界面。

如果获取到的分组信息是不需要登录的,那么就直接通过InterceptorCallback执行onContinue继续路由到对应地址。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Awesome_lay

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值