前言:
这篇文章介绍的是 - 初级路由,不是ARouter!, 建议在单独组件中使用,当然如果你想跨组件使用也是可以的,前提是该组件有正确的引用关系,比如两个组件间的界面跳转,组件A跳到组件B的时候A内需要有B的引用,ARouter可以实现不同组件之间没有引用关系可以进行跳转,是因为在编译的时候通过APT把相关数据已经单独拿出来了,使用时通过反射的原理拿到相关的数据,就可以进行操作了。
如果你想跨组件使用,建议还是使用ARouter。
为什么
如何写路由之前,还是要先说一下为什么要使用路由,使用路由的优势以及劣势。
背景: 随着APP业务需求以及逻辑越来越复杂,开发者的代码量以及入门项目的门槛越来越高,特别是业务量特别庞大的项目。如果没有及时优化,比如组件化等,随着需求越来越多会暴露出很多问题。
优势: 路由很适合复杂的业务场景,用专业术语就是 简化代码,解耦。而且也适合慢慢进行迭代,不会对原有框架以及功能产生太大影响。
缺点: 因为路由牺牲了耦合还有解耦,所以需要将业务逻辑集中处理,为了区分不同业务场景,所以会产生大量的"编号"(常量),这里可以用功能号以及界面号的思维,比如 A界面用常量
public static final String A = "A";
代替, 跳转到XX界面用
public static final String B = "B";
来代替, 这里强烈建议每个常量要进行注释,表明是啥含义,否则新伙伴可能要口吐芬芳了。
其他: 上述引出了 功能号、界面号的思想,这里是非常建议大家去使用的,通过特定的常量去代表某一功能或者方法,很直观,也减少了代码量,用起来很舒服。
路由写法有很多,这里只分享我接触的一种,大佬勿喷。
实践:
条件: 一个接口,一个存放编码(功能号,界面号)的类,路由类(可放在公共组件内),具体实现类(放在对应的组件里)
介绍: 接口里写相关方法,路由类里面进行相关接口以及编码的存储,并通过不同的编码返回不同接口回调,从而在相对的的实现类里面操作,这里存储用到的是 ConcurrentHashMap(简介:官方建议的,线程安全的,效率高的集合)
注意: 路由在使用前需要进行注册(用于存储数据在路由类里面,一般放在Application里面),实现类需要继承接口,在该接口的相关方法里进行回调,
效果: 发送路由,实现相关功能。
实现代码(都已在注释中表明):
接口
/**
* 作者:zch
* 时间:2022/4/24 10:21
* 描述:路由接口
*/
public interface MyRouterCallBack {
//路由方法,根据需求可以写多个
MyRouter doCallBack(Map<String, Object> reqMap);
}
路由类
/**
* 作者:zch
* 时间:2022/4/24 10:08
* 描述:路由类
*/
public class MyRouter {
//用于存储接口和对应的编码号,根据编码拿出对应的接口,进行操作
private ConcurrentHashMap<String, Object> mTztRouterActions;
//单例模式或者实例
private static MyRouter myRouter;
public static MyRouter getIns(){
if (myRouter == null){
myRouter = new MyRouter();
}
return myRouter;
}
//注册路由,也就是将路由存储在集合里
public void registerRouter(String action, MyRouterCallBack callBack) {
//非空判断,防止重复创建实例
if (mTztRouterActions == null){
mTztRouterActions = new ConcurrentHashMap<>();
}
//如果存在就移除重新添加,防止重复,所以相同编码号是不能重复注册的
if (mTztRouterActions.containsKey(action)){
mTztRouterActions.remove(action);
}
//添加到集合里
mTztRouterActions.put(action,callBack);
}
//路由操做
public MyRouter callRouter(Map<String, Object> reqMap){
//拿到编码号
String o = (String)reqMap.get(MyNumber.key);
//条件判断
if (!TextUtils.isEmpty(o) && mTztRouterActions != null){
//拿到对应的接口实例
MyRouterCallBack mRouter = (MyRouterCallBack)mTztRouterActions.get(o);
if (mRouter != null){
//接口内方法操作,在对应的实现类里面回进行响应,也就是在对应类里面进行操作
mRouter.doCallBack(reqMap);
}
}
return this;
}
}
编码类
/**
* 作者:zch
* 时间:2022/4/24 15:07
* 描述:存放编码类
*/
public class MyNumber {
//通过HashMap传递信息,者个是统一的存放编码号的key,下面的编码号放到value里面
public static final String key = "Key";
//不同的编码号,要对应不用的功能
public static final String A = "A";
//不同的编码号,要对应不用的功能
public static final String B = "B";
//不同的编码号,要对应不用的功能
public static final String C = "C";
//不同的编码号,要对应不用的功能
public static final String D = "D";
}
具体实现类
/**
* 作者:zch
* 时间:2022/4/24 10:50
* 描述:具体实现类
*/
public class MyRouter_now implements MyRouterCallBack {
//单例获取实例
@SuppressLint("StaticFieldLeak")
private static MyRouter_now myRouter_now;
private Context c;
public static MyRouter_now getIns(Context c){
if (myRouter_now == null){
myRouter_now = new MyRouter_now();
}
myRouter_now.c = c;
return myRouter_now;
}
//不同的编码号以及接口注册,因为该类以及实现了相关接口,所以之间用 this 即可
public void registerRouter() {
MyRouter.getIns().registerRouter(MyNumber.A,this);
MyRouter.getIns().registerRouter(MyNumber.B,this);
MyRouter.getIns().registerRouter(MyNumber.C,this);
MyRouter.getIns().registerRouter(MyNumber.D,this);
}
//接口回调
@Override
public MyRouter doCallBack(Map<String, Object> reqMap) {
//回调过来的 Map,拿到对应的编码号
String wwe = (String) reqMap.get(MyNumber.key);
//防异常
try {
//根据不同的编码号进行不同的操作,在这集中处理
switch (Objects.requireNonNull(wwe)){
case MyNumber.A:
Toast.makeText(c.getApplicationContext(),"我是A的操作",Toast.LENGTH_SHORT).show();
break;
case MyNumber.B:
Toast.makeText(c.getApplicationContext(),"我是B操作",Toast.LENGTH_SHORT).show();
break;
case MyNumber.C:
Toast.makeText(c.getApplicationContext(),"我是C操作",Toast.LENGTH_SHORT).show();
break;
case MyNumber.D:
Toast.makeText(c.getApplicationContext(),"我是D操作",Toast.LENGTH_SHORT).show();
break;
default:
break;
}
}catch (Exception e){
e.printStackTrace();
}
return null;
}
}
Activity
public class MainActivity extends AppCompatActivity{
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//注册路由,正常在Application那里注册
MyRouter_now.getIns(getBaseContext()).registerRouter();
findViewById(R.id.tv_o).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//发送路由,不管想要使用什么方法,都可通过此方式,前提是 规定好编码号,路由那里进行注册,才能正常使用
HashMap<String, Object> hashMap = new HashMap<>();
//编码号 key 固定,用于路由类获取,后面对应操作
hashMap.put(MyNumber.key,MyNumber.D);
MyRouter.getIns().callRouter(hashMap);
}
});
}
}
以上就是路由类的全部内容,仅仅提供一个思想方式。