Router_一款单品、组件化、插件化全支持的路由框架

@RouteConfig(baseUrl=“haoge://page/”)
public class App extends Application {

}

下表是路由前缀与路由地址之前的匹配关系,横排表示RouteRule配置的路由地址,竖排表示baseUrl:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

自动解析url参数

Router的自动参数解析。是结合的Parceler框架来进行使用的,关于Parceler框架的介绍可以参考下方的链接:

Parceler: 优雅的使用Bundle进行数据存取就靠它了!

请注意:Parceler框架并不是Router所必须依赖的框架。只是添加此框架使用后,能使用更强大的特性。

如果不使用的话。所有的url参数。都将默认解析为String并进行传递。

  1. 参数自动转换:

首先。我们先在Activity基类中配置注入入口,配置此入口后。就会自动从intent中读取对应的数据。注入到子类中的被Arg注释过的成员变量中去了:

public class BaseActivity extends Activity {

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Parceler.toEntity(this,getIntent());
}
}

假设当前我们有以下一个页面:

@RouterRule(“haoge://page/example”)
public class ExampleActivity extends BaseActivity {
@Arg
String name;
@Arg
long id;
@Arg
boolean isLogin;

}

可以看到。这个页面含有三个属性。并都添加了Arg注解。那么此时我们可以以下方的链接来进行跳转传参:

Router.create(“haoge://page/example?name=haoge&id=10086&isLogin=false”).open(context);

链接中的参数将会自动根据Arg注解的类型进行自动转换。并在转换后转载入Intent中进行传递. 即相当于以下的操作:

String url = “haoge://page/example?name=haoge&id=10086&isLogin=false”;
Uri uri = Uri.parse(url);
Bundle bundle = new Bundle;
bundle.putString(“name”, uri.getQueryParameter(“name”))
bundle.putLong(“id”,
Long.parseLong(uri.getQueryParameter(“id”)));
bundle.putBoolean(“isLogin”,
Boolean.parseBoolean(uri.getQueryParameter(“isLogin”)));

// 启动路由并传递bundle

此种自动转换类型的参数。只支持基本数据类型。若Arg所注释的属性类型不为基本数据类型。则不触发自动转换,将读取的String串直接存入Intent中。

  1. 传递复杂参数

但是很多时候我们的传参数据又不止是基本数据类型。比如说普通实体bean。比如说一个列表。所以这就是Parceler展现光芒的时候了!

Parceler自带JSON数据转换功能。对于传递的是非基本数据类型的。则可以在参数中传递此类型的json串:这也是为什么推荐引入Parceler框架进行使用的原因:小而强大!

复杂参数需要使用Parceler的转换功能,关于数据转换器。也在上面那篇文章中有描述。这里我使用的是FastJson的转换器:

Parceler.setDefaultConverter(FastJsonConverter.class);

首先假设当前有个此页面, 需要传参为普通实体类User:

@RouterRule(“usercenter”)
public class UserCenterActivity extends BaseActivity{
@Arg
User user;
}

public class User {
public String username;
public String password;

}

那么就可以通过以下链接进行跳转:

// 这里为了理解方便,我没有直接拼装链接。
User user = new User(“router”, “123456”);
String json = JSON.toJSONString(user);
// 对json串需要先进行url编码。
String encodeJson = URLEncoder.encode(json);
String url = String.format(“haoge://page/usercenter?user=%s”, encodeJson);
Router.create(url).open(context);

可以看到,通过此种方式,可以直接传递具体的json数据进行传递。请注意对于链接中的json数据。一定要先进行encode编码。避免内部uri解析异常。

由于目标页对应的user类型不为基本数据类型。所以此处将直接将user所指代的值。自动解码后直接放入Intent中传递入目标页。目标页中则会使用Parceler自动将此json转换解析成User类。完成复杂参数的传递

动作路由

上面所介绍的。都是通过一个链接。打开一个对应的页面。此种路由跳转称为页面路由。

Router也支持另一种路由:动作路由,此种路由没有页面跳转。只是用于做一些特殊的操作。

比如说:加入购物车、清空购物车数据、退出登录等。

@RouterRule(“shopcar.clear”)
public class ClearShopcarAction extends ActionSupport {
@Override
public void onRouteTrigger(Context context, Bundle bundle) {
// TODO 清空购物车操作
}
}

然后即可通过以下链接触发清空购物车操作:

Router.create(“haoge://page/shopcar.clear”).open(context);

额外请求参数

上面举的例子。都是全部数据通过一个url直接传递。但是很多时候。我们是需要在此url的基础上。再额外添加一些别的数据进行传递的。比如转场动画配置、requestCode配置、Intent.flags配置等.

Router.create(url)
.addExtras(bundle) // 添加额外bundle数据参数
.requestCode(code) // 用于startActivityForResult
.setAnim(enterAnim, exitAnim)// 转场动画
.addFlags(flag)// intent.addFlags(flag);
.addInterceptor(interceptor)// 添加拦截器
.setCallback(callback)// 设置路由回调
.open(context);

添加路由回调

在讲路由表的时候有提到过,路由是一种特殊的启动流程,且启动不一定成功。所以很自然的,这个时候就需要有一个路由回调接口。

路由回调接口为RouteCallback类:

public interface RouteCallback {
// 当路由寻址失败时。触发此回调
void notFound(Uri uri, NotFoundException e);
// 当路由启动成功时。触发此回调
void onOpenSuccess(Uri uri, RouteRule rule);
// 当路由启动失败时。触发此回调。包括
void onOpenFailed(Uri uri, Throwable e);
}

路由回调配置分为两种:

  • 全局路由回调:所有的路由启动事件。都会触发此回调

RouterConfiguration.get().setCallback(callback);

  • 局部路由回调:只被当前路由启动触发。

Router.create(url)
.setCallback(callback)
.open(context);

路由回调在进行页面跳转埋点时,会是非常有用的一个特性。

日志打印

当配置Router.DEBUG为true时(默认为false)。框架将会启用内部日志输出。建议使用BuildConfig.DEBUG进行日志开关控制, 达到在只在开发时进行日志输出的作用:

Router.DEBUG = BuildConfig.DEBUG

日志可通过RouterLog进行过滤查看

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

拦截器

顾名思义:拦截器就是用于在路由启动过程中,进行一系列的提前检查,当检查不符合规则时,则使此次路由启动失败。

举个最经典的案例:登录检查

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

当不使用路由进行跳转时,这种情况就会导致你本地写上了大量的登录判断逻辑代码。这在维护起来是很费劲的。而且也非常不灵活,而使用拦截器的方式来做登录检查,就会很方便了:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

下面是一个简单的登录拦截实现:

// 实现RouteInterceptor接口
public class LoginInterceptor implements RouteInterceptor{
@Override
public boolean intercept(Uri uri, RouteBundleExtras extras, Context context){
// 未登录时进行拦截
return !LoginChecker.isLogin();
}

@Override
public void onIntercepted(Uri uri, RouteBundleExtras extras, Context context) {
// 拦截后跳转登录页并路由信息传递过去,便于登录后进行恢复
Intent loginIntent = new Intent(context,LoginActivity.class);
// uri为路由链接
loginIntent.putExtra(“uri”,uri);
// extras中装载了所有的额外配置数据
loginIntent.putExtra(“extras”,extras);
context.startActivity(loginIntent);
}
}

public class LoginActivity extends BaseActivity {

@Arg
Uri uri;
@Arg
RouteBundleExtras extras;

void onLoginSuccess() {
if(uri != null) {
// 登录成功。使用此方法直接无缝恢复路由启动
Router.resume(uri, extras).open(context);
}
finish();
}
}

拦截器功能是Router框架的重点,且经过长时间的迭代。Router目前提供三种拦截器提供使用,你可以根据你自己的需要。灵活的选择使用什么类型的拦截器。

1. 全局默认拦截器:

设置方式:RouterConfiguration.get().setInterceptor(interceptor);

作用域:此全局默认拦截器。将会被所有启动的路由事件所触发。

推荐使用场景

一些需要进行全局判断的检查:比如登录检查等。且最好此处所配置的拦截器。添加上对应的开关控制。

比如说做登录检查的,控制如果有requestlogin参数的才启用登录检查。将登录检查控制交给提供url的地方。

2. 针对某次路由所特别设置的拦截器

设置方式:Router.create(url).addInterceptor(interceptor);

作用域:只被此处所创建的路由触发。

推荐使用场景:一些只在此处启动路由时才需要触发的检查:比如deeplink外部链接入口处,检查外部链接是否合法等。

3. 针对某个目标路由所特别设置的拦截器

设置方式:在配置了RouterRule的目标类上。添加@RouteInterceptor()注解。将需要配置的注解Class加入:

@RouteInterceptors(CustomInterceptors.class)
@RouterRule(rule)
public class ExampleActivity extends Activity {}

作用域:当路由url所匹配的目标路由为此路由时被触发

推荐使用场景:针对此页面跳转的的检查,比如对传递参数进行过滤,避免传入无效数据导致不可期异常等。

此三种拦截器,触发的优先顺序为:全局默认 > 某次路由 > 某个目标路由,且若当此路由已被某个拦截器拦截了。则将不会继续触发后续拦截器

Router在组件化环境下进行使用

对于组件化中使用Router框架。可以参考此处放于github上的组件化demo

可结合上方demo与下方描述一同查看。达到更加方便理解的作用!

在组件化环境下使用路由框架。主要需要考虑以下几点:

注册多个路由表

由于Router本身没有使用自动注册的方式来进行路由表注册。而是提供了相应的接口、相应的方法来手动注册,这种配置方式本身即可做到动态注册多个路由表的效果:

RouterConfiguration.get().addRouteCreator(routeCreator);

所以在组件化中进行使用。只要想办法注册多个组件自身生成的路由表即可。

激活业务组件的注解处理器

路由表类的生成,是在编译时自动生成的。而编译时生成框架的作用域只在当前module中。所以需要将Router的注解处理器,分别配置添加到每个业务组件之中,使每个业务组件都能够使用注解生成自身的路由表类:

annotationProcessor “com.github.yjfnypeu.Router:router-compiler:2.6.0”

而组件化中,对于使用的注解处理器。推荐的做法是将所有需要使用的注解处理器都抽离到一个统一的gradle脚本中。然后由各个组件直接apply应用即可:

创建processor.gradle:

dependencies {
annotationProcessor “com.github.yjfnypeu.Router:router-compiler:2.6.0”
…// 所有注解处理器均放置于此配置
}

然后在组件中的build.gradle中直接通过apply from方法应用此脚本即可。

这样的做法有以下几点好处:

  1. 由于编译时注解的注解处理器。是直接提供给IDE进行使用的。并不会再打包时将对应的代码打包进apk中。所以不用担心引入额外的不需要的代码进入apk中。
  2. 便于版本升级统一控制

避免多个组件生成的路由表冲突

在单品环境下使用时。有介绍会在编译时生成一个具体的路由表类RouterRuleCreator, 而这个类生成的包名是默认写死的:com.lzh.router.

所以在多组件环境下进行使用时,需要对每个module指定不同的生成路由表类的包名。避免出现重复类冲突问题:

@RouteConfig(pack=“com.router.usercenter”)
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数初中级Android工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则近万的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。

img

img

img

img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

如果你觉得这些内容对你有帮助,可以扫码获取!!(备注:Android)

《设计思想解读开源框架》

第一章、 热修复设计

  • 第一节、 AOT/JIT & dexopt 与 dex2oat

  • 第二节、 热修复设计之 CLASS_ISPREVERIFIED 问题

  • 第三节、热修复设计之热修复原理

  • 第四节、Tinker 的集成与使用(自动补丁包生成)

    第二章、 插件化框架设计

  • 第一节、 Class 文件与 Dex 文件的结构解读

  • 第二节、 Android 资源加载机制详解

  • 第三节、 四大组件调用原理

  • 第四节、 so 文件加载机制

  • 第五节、 Android 系统服务实现原理

    第三章、 组件化框架设计

  • 第一节、阿里巴巴开源路由框——ARouter 原理分析

  • 第二节、APT 编译时期自动生成代码&动态类加载

  • 第三节、 Java SPI 机制

  • 第四节、 AOP&IOC

  • 第五节、 手写组件化架构

    第四章、图片加载框架

  • 第一节、图片加载框架选型

  • 第二节、Glide 原理分析

  • 第三节、手写图片加载框架实战

    第五章、网络访问框架设计

  • 第一节、网络通信必备基础

  • 第二节、OkHttp 源码解读

  • 第三节、Retrofit 源码解析

    第六章、 RXJava 响应式编程框架设计

  • 第一节、链式调用

  • 第二节、 扩展的观察者模式

  • 第三节、事件变换设计

  • 第四节、Scheduler 线程控制

    第七章、 IOC 架构设计

  • 第一节、 依赖注入与控制反转

  • 第二节、ButterKnife 原理上篇、中篇、下篇

  • 第三节、Dagger 架构设计核心解密

    第八章、 Android 架构组件 Jetpack

  • 第一节、 LiveData 原理

  • 第二节、 Navigation 如何解决 tabLayout 问题

  • 第三节、 ViewModel 如何感知 View 生命周期及内核原理

  • 第四节、 Room 架构方式方法

  • 第五节、 dataBinding 为什么能够支持 MVVM

  • 第六节、 WorkManager 内核揭秘

  • 第七节、 Lifecycles 生命周期


    本文包含不同方向的自学编程路线、面试题集合/面经、及系列技术文章等,资源持续更新中…

《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》,点击传送门即可获取!
  • 第一节、 LiveData 原理

  • 第二节、 Navigation 如何解决 tabLayout 问题

  • 第三节、 ViewModel 如何感知 View 生命周期及内核原理

  • 第四节、 Room 架构方式方法

  • 第五节、 dataBinding 为什么能够支持 MVVM

  • 第六节、 WorkManager 内核揭秘

  • 第七节、 Lifecycles 生命周期

    [外链图片转存中…(img-OfcQ1KsB-1712296969317)]
    本文包含不同方向的自学编程路线、面试题集合/面经、及系列技术文章等,资源持续更新中…
    [外链图片转存中…(img-Y7DXXWOW-1712296969318)]

《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》,点击传送门即可获取!
  • 14
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值