利用 APT 处理应用内跳转协议

1,369 阅读3分钟
原文链接: www.jianshu.com

概述

之前看过天猫的关于统跳协议的文章。 其实跳转协议这东西,应该属于稍微成熟一点的app的必备模块。

跳转协议主要为了解决 app 的几个问题:

  • 应用外到应用内的跳转
  • 应用内部的跳转。 尤其在大型项目上, 不同的模块之间的跳转
  • H5 与 native 之间的跳转

处理方式

为每个项目定义一个专属的协议, 例如:
yxl://github.io/o.c?action=login
其中:
yxl :协议
github.io : host
o.c :路径
action :当前链接的动作, 即打开 login 页面。 后面可继续加参数

当内部组件收到跳转链接, 并解析出符合定义的 action 之后, 根据 action 值跳转到对应的界面。一般为了节省跳转链接占用字符的长度, 路径不设置。

处理逻辑很简单, 但是能够跳转的前提是对应的 action 已经被定义过了, 组件知道要跳转到哪。 所以在应用启动的时候就需要将所有的 action 动作都注入到组件内。

最开始我们的解决办法是手工注入。由于不同的模块都在不同的 Module 下开发, 我们定义了一个统一的接口, 应用启动的时候会逐一调去每个 module 的启动接口, 然后在这个内各自将自己的 actions 注入到跳转组件内。

这种处理方法太繁琐, 开发人员不仅需要定义处理, 还需要记着主动注入。 而且这种操作增加一个减少一个或者某个需要修改,牵扯的地方都很多, 维护性上也不好。

升级方案

利用 apt 技术, 开发人员创建 action 的处理类的时候, 通过注解标注对应的 action 动作。 然后通过 apt 插件在编译过程扫描生成一个包含所有 action 对象的清单文件, 在 app 启动的时候根据这个清单自动加载就可以。

开源库

处理代码已开源在 github bjaction 仓库。

集成方式:
  • 在 project 的 build.gradle 文件中引入 apt 插件

    'com.neenbedankt.gradle.plugins:android-apt:1.8'

  • 在需要处理跳转的 module 的 build.gradle 文件增加插件和类库依赖

    apply plugin: 'com.neenbedankt.android-apt'

    compile 'io.github.yangxlei:bjaction:1.0.0'
    apt 'io.github.yangxlei:bjaction-compile:1.0.0'

使用
@ActionType("test2")
public class Test2Action implements BJAction.BJActionHandler {

    @Override
    public void doPerform(Context context, String type, Map payload) {
        Test2Activity.launch(context);
    }
}

创建一个 BJActionHandler 的子类, 并使用 @ActionType 标注对应的 action 值.

bjaction-compile 会为每个 module 生成一个 ModuleActionTypes
的 java 文件。 在 应用启动时注入到 bjaction 组件内。

public class MyApplication extends Application {

    @Override
    public void onCreate() {
        super.onCreate();

        //yxl://github.io/o.c?action=xx&xx=xx
        BJActionUtil.initialize("yxl", "github.io", "o.c", "action", new BJActionUtil.BJActionDefaultHandler() {
            @Override
            public void onHandleDefault(Context context, String schema) {
                //goto webview
            }
        });
      //加载每个 module 的 ModuleActionTypes 配置
       BJActionUtil.loadActions(io.github.yangxlei.actionhandle.actions.ModuleActionTypes.getModuleActionTypes());
        BJActionUtil.loadActions(yangxlei.github.io.app2.actions.ModuleActionTypes.getModuleActionTypes());

    }
}

在应用启动时, 同样将 schema, host, action 初始化到 bjaction 组件内。

执行跳转

  findViewById(R.id.button_test1).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                BJActionUtil.sendToTarget(MainActivity.this, /*yxl://github.io/o.c?action=test1*/
                        BJActionUtil.buildActionUrl("test1", null));
            }
        });

其实不光只是跳转, 可以通过协议定义任何的 action ,执行任何操作; 因为 action 也是单独定义的, 所以不需要修改原来的任何东西。

参考资料:

javapoet
android-apt