Android 彻底组件化—如何使用 Arouter

作者:格竹子
链接:https://www.jianshu.com/p/aa17cf4b2dca
声明:本文是 格竹子 原创。转载请联系作者获得授权。

得到 Android 组件化方案已经开源,参见 Android 组件化方案开源(https://link.jianshu.com/?t=https%3A%2F%2Fgithub.com%2Fluojilab%2FDDComponentForAndroid)。方案的解读文章是一个小的系列,这是系列的第五篇文章:
1、Android彻底组件化方案实践(https://www.jianshu.com/p/1b1d77f58e84
2、Android 彻底组件化 demo 发布
3、Android彻底组件化-代码和资源隔离(https://www.jianshu.com/p/c7459b59dcd5
4、Android彻底组件化—UI跳转升级改造(https://www.jianshu.com/p/03c498e05a46
5、Android彻底组件化—如何使用Arouter(https://www.jianshu.com/p/aa17cf4b2dca

上篇文章(https://www.jianshu.com/p/03c498e05a46)讲到,DDComponent(https://link.jianshu.com/?t=https%3A%2F%2Fgithub.com%2Fluojilab%2FDDComponentForAndroid)已经进行了UI跳转的升级改造,可以支持路由的自动注册和路由表的自动生成。但是很多使用组件化方案的同学都表示项目中已经接入 ARouter 来进行 UI 跳转,迁移成本比较高。因此我就专门写了这篇文章,讲解一下如何在组件中使用 ARouter。

不论用 DDComponent 自带的方案还是 ARouter,要做到组件之间自由并且可控的跳转,需要做到下面几点:

1、路由跳转需要支持传递基本类型和自定义类型(例如 Object)
2、路由的跳转需要和组件的生命周期一致,即只有加载的组件才可以跳转,卸载后的组件是不可达的
3、最好生成路由表,组件对外提供的路由可以轻松查阅到

下面我们就从配置开始一步步的讲怎么使用 ARouter

增加必要的配置

basiclib 模块中增加以下依赖,basiclib 是组件化框架中共用的依赖库:

compile 'com.alibaba:arouter-api:1.3.0'

在跳转的目标组件的build.gradle中,增加以下配置:

android {
   defaultConfig {
   ...
   javaCompileOptions {
       annotationProcessorOptions {
       arguments = [ moduleName : project.getName() ]
       }
   }
   }
}
dependencies {
   annotationProcessor 'com.alibaba:arouter-compiler:1.1.4'
   ...
}

在组件化框架中,我们的示例是从 readercomponent 跳转到 sharecomponent,所以上述配置增加在 sharecomponent 下面的 build.gradle 中。

在目标页面增加相应的注解

我们以“分享图书” 页面为例

@Route(path = "/share/shareBook")
public class ShareActivity extends AppCompatActivity {

在进入这个页面,需要传入两个参数,一个是String类型的bookName,一个是自定义类型Author的author

@Autowired
String bookName;
@Autowired
Author author;

如何传递自定义类型

由于自定义类型Author需要跨组件传递,我们知道,DDComponent的核心之处就是在组件之间见了一堵墙,在编译期代码和资源都是完全隔离的,所以Author必须定义在share组件向外提供的服务中。所以我们在component中,定义Author类:

public class Author {
   private String name;
   private int age;
   private String county;
   public String getName() {
       return name;
   }
   public void setName(String name) {
       this.name = name;
   }
   public int getAge() {
       return age;
   }
   public void setAge(int age) {
       this.age = age;
   }
   public String getCounty() {
       return county;
   }
   public void setCounty(String county) {
       this.county = county;
   }
}

现在就解决了Author的可见性问题,但是为了能在路由中传递,按照ARouter的要求,还需要自己实现SerializationService:

@Route(path = "/service/json")
public class JsonServiceImpl implements SerializationService {
   @Override
   public void init(Context context) {}
   @Override
   public <t> T json2Object(String text, Class<t> clazz) {
       return JSON.parseObject(text, clazz);
   }
   @Override
   public String object2Json(Object instance) {
       return JSON.toJSONString(instance);
   }
   @Override
   public <t> T parseObject(String input, Type clazz) {
       return JSON.parseObject(input, clazz);
   }
}

这里笔者就遇到了一个坑,本来我把这个类定义在readercomponent中,结果运行之后会报空指针异常。只有我把类移到sharecomponent之后,异常才消失。暂时没找到原因,但是定义在这里,加入要跳转到readercomponent怎么办呢?

发起跳转

在组件化框架demo中,发起跳转是readercomponent中的ReaderFragment中,demo中列出了两个示例:
普通跳转

private void goToShareActivityNormal() {
   Author author = new Author();
   author.setName("Margaret Mitchell");
   author.setCounty("USA");
   ARouter.getInstance().build("/share/shareBook")
           .withString("bookName", "Gone with the Wind")
           .withObject("author", author)
           .navigation();
}

以及startActivityForResult

private void goToShareActivityForResult() {
   Author author = new Author();
   author.setName("Margaret Mitchell");
   author.setCounty("USA");
   ARouter.getInstance().build("/share/shareMagazine")
           .withString("bookName", "Gone with the Wind")
           .withObject("author", author)
           .navigation(getActivity(), REQUEST_CODE);
}

控制生命周期

经过上面的操作,已经可以完成UI跳转了。但是如果运行demo就可以发现,此时即使卸载了分享组件,分享书的页面还是可以进入的,说明生命周期没有同步。在DDComponent自带的方案中是不存在这个问题的,因为跳转的逻辑已经与组件化生命周期绑定在一起。
这里就用到ARouter自带的拦截器功能,每个组件都需要定义一个拦截器,当组件卸载之后需要拦截住该组件的跳转入口。
下面是分享组件拦截器的示例代码:

@Interceptor(priority = 1, name = "分享组件拦截器")
public class ShareInterceptor implements IInterceptor {
   public static boolean isRegister;
   Context mContext;
   @Override
   public void process(Postcard postcard, InterceptorCallback callback) {
       if (isRegister) {
           callback.onContinue(postcard);
       } else if ("/share/shareBook".equals(postcard.getPath())
               || "/share/shareMagazine".equals(postcard.getPath())) {
           MainLooper.runOnUiThread(new Runnable() {
               @Override
               public void run() {
                   Toast.makeText(mContext, "分享组件已经卸载", Toast.LENGTH_SHORT).show();
               }
           });
       }
   }
   @Override
   public void init(Context context) {
       mContext = context;
   }
}

这里通过一个isRegister开关来控制拦截器是否生效,为了保证生命周期一致性,在ShareApplike中增加赋值逻辑:

public class ShareApplike implements IApplicationLike {
   @Override
   public void onCreate() {
       ShareInterceptor.isRegister = true;
   }
   @Override
   public void onStop() {
       ShareInterceptor.isRegister = false;
   }
}

但是这里也遇到了两个小坑,不知道是否是ARouter使用不当:
(1)添加或者修改拦截器之后,必须卸载重装app才能生效,不论是clean还是rebuild都是不生效的
(2)拦截器中需要硬编码该组件的所有路由,例如/share/shareBook等,一旦路由发生了改变,一定要记得修改这个地方

路由表生成

这个ARouter暂时没有提供,DDComponent自带的方案增加了这个功能,当组件build生成之后,在根目录生成UIRouterTable文件夹,里面会列出每个组件向外提供的路由表以及具体参数

auto generated, do not change !!!! 
HOST : share
分享杂志页面
/shareMagazine
author:com.luojilab.componentservice.share.bean.Author
bookName:String
分享书籍页面
/shareBook
author:com.luojilab.componentservice.share.bean.Author
bookName:String

这点对于组件的协同开发是比较重要的,毕竟跳转之前翻阅别人的代码是件比较费事的工作

简单做一个总结:

(1)ARouter 是一个优秀的路由跳转方案,DDComponent 自带的方案也参考了很多其中的想法,功能很强大
(2)使用中需要与组件化方案兼容的地方主要是生命周期相关,在拦截器上增加部分逻辑就可以完成
(3)ARouter 使用中还存在一些小的问题,可能是姿势不对,接入中走了不少弯路,有熟悉这块的朋友可以指出原因
(4)路由表没有自动生成,对外没有暴露有哪些路由协议和参数,对于组件之间协同开发不太友好

上面的代码已经发布 DDComponent 的 master-arouter 分支,欢迎大家使用,源码地址: https://github.com/luojilab/DDComponentForAndroid


  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值