实现项目组件化必经之路:解耦,再解耦!

一个组件化的项目,会将业务进行细化的拆分,通用的功能封装在通用的模块中,不同通用功能模块之间是平级的关系,不同的业务模块会按需依赖其中几个通用模块。
1_app通用架构

如上图所示,业务A无法调用业务B中的API,同样业务B也无法打开业务A中的页面,这两个业务模块是独立的,通用模块之间也是如此。

模块间如果需要访问API,得建立强依赖关系,项目的耦合度会变得非常高,通用模块因为需要多种依赖而失去了它通用的特性。

因此我们需要一种松耦合的方式,建立平级模块间的通信方式,实现组件化。

模块间需要通信的场景有很多种,例如访问页面,UI事件通知、回调等等。本文为大家介绍一个我自己写的帮助实现项目组件化的库:KRouter,它是一个非常轻巧、高效、稳定的安卓组件库,它使用kotlin编写,能够运用于java、kotlin甚至混编项目,它支持多模块,通过注解的方式,能非常方便地解决无依赖关系模块间页面访问、API调用问题。

在写本文时,KRouter已经开发到1.0.4版本,且仍然在维护中,读者可以访问项目github地址:https://github.com/jamgudev/KRouter,获取最新的版本信息。

如果您觉得该库实用的话,欢迎start和fork,如果您发现该库存在bug或还有改进的地方,欢迎提交issues或提交pull requests

接下来,我为大家简单说下如何使用KRouter。

正文
如何使用

首先引入该库,编辑你的工程build.gradle文件,在文件中添加插件地址:

buildscript {
    dependencies {
        classpath "io.github.jamgudev:krouter-plugin:1.0.4"
    }
}

并在application module中引用插件:

plugins {
    id 'com.jamgu.krouter.plugin'
}

添加完后,同步一下代码就可以使用KRouter的所有功能了。

你可能会疑惑,支持注解的库都需要注解处理器,为什么没有添加注解处理器的依赖就可以使用?

实际上添加其他依赖库的操作,com.jamgu.krouter.plugin插件帮你自动完成了。我将其他依赖库的最新版本号内置在了插件中,你只需要使用最新版本的plugin插件,理应可以获得所需依赖库的最新版本。

你也可以在工程的build.gradle文件中指定依赖库的版本:

ext {
	krouter_core_version = "1.0.4" // edit the version number you need
	krouter_compiler_version = "1.0.3"
	
	// flag whether to print compiler logs 
	krouter_compile_loggable = false
}
多模块支持

如果你除了主工程模块外,其他依赖模块也需要使用KRouter,只需要在相应模块的build.gradle中应用krouter插件即可:

plugins {
    id 'com.jamgu.krouter.plugin'
}
简单使用

Activity路由

@KRouter(value = "setting_activity", intParams = {"userId", "gameId"}, stringParams = {"user_name"})
public class SettingActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_setting);
    }
}

// 简单调用
KRouters.open(context, "setting_activity");
// 带参数调用
KRouters.open(context, new KRouterUriBuilder("router")
              .with("userId", 10000)
              .with("gameId", 20010)
              .with("user_name", "jamgu")
              .build());
// startForResult
KRouters.openForResult(context, "setting_activity", 10010);
// activity routers api
Intent intent = KRouters.getRawIntent(this, "setting_activity");
registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), (callback) -> {})
          .launch(intent);

为Activity路由注册全局拦截器

KRouters.registerGlobalInterceptor(new IRouterInterceptor() {
    @Override
    public boolean intercept(@NotNull Uri uri, @Nullable Bundle bundle) {
        Log.d(TAG, "uri = " + uri + " bundle = " + bundle);
        return false;
    }
});

intercept()方法返回true时,拦截本次路由,不会跳转。

Fragment路由

@KRouter(value = "main_frag", intParams = "col_id")
public class MainFragment extends Fragment {}

// 配置注解后可以通过main_frag获取该fragment实例
Fragment fragment = KRouters.createFragment(context, "main_frag");

Method路由

@MethodRouter(value = "get_some_state2")
public static boolean getSomeState(Map<String, Object> map, IAsyncMethodCallback<Boolean> callback) {
    // do something
    // 如果传递了参数,可以通过如下方式取
    String userName = (String) map.get("userName");
    long userId = Long.parseLong(map.get("userId").toString());
    Log.d("jamgu", "hhhh userID = " + userId);
    return false;
}

// 简单调用,不传递参数,此时map为null,
MethodRouters.invoke("get_some_state2");
// 带参数传递
boolean state = MethodRouters.invoke("get_some_state2", new MethodMapBuilder()
                     .with("userId", "12345")
                     .with("userName", "jamgu")
                     .build());
// 带参数传递,同时传递一个回调,回调位置由用户决定
MethodRouters.invoke("get_some_state2", new MethodMapBuilder()
                     .with("userId", "12345")
                     .with("userName", "jamgu")
                     .build(), new IAsyncMethodCallback<Integer>() {
                       @Override
                       public void onInvokeFinish(Integer integer) {
                         // 供其他地方指定的回调
                       }
                     });

MethodRouter限制较大,MethodRouter注解仅支持静态方法,只允许传递最多两个参数,传递的参数类型只能是Map类型,或者IAsyncMethodCallback类型,且不能同时传递两个Map类型或Callback类型

例如你可以将MethodRouter注解运用到如下格式的静态方法中

@MethodRouter(value = "xxx")
public static void getSomeState() {
    // 空返回类型,无需传递参数 
    return;
}

@MethodRouter(value = "xxx")
public static Integer getSomeState(Map<String, Object> map) {
    // Integer返回值类型,可支持一个Map类型参数
    // 调用时可以不传map,不传递时,map为null
    return 0;
}

@MethodRouter(value = "xxx")
public static Integer getSomeState(Map<String, Object> map, IAsyncMethodCallback<Integer> callback) {
  // 支持传递两个参数,若都不传递,则两参数为null
  return 0;
}

KRouter的简单用法就说到这,更多用法就交给大家去探索了~

如果在使用KRouter时发现了bug或觉得有任何地方需要改进的,欢迎反馈!我需要你们的建议不断完善!

兄dei,如果觉得我写的还不错,麻烦帮个忙呗 😃
  1. 给俺点个赞被,激励激励我,同时也能让这篇文章让更多人看见,(#.#)
  2. 不用点收藏,诶别点啊,你怎么点了?这多不好意思!

拜托拜托,谢谢各位同学!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值