哪个国家代孕正规?

█微信号█  13★710097773 █供卵试管婴儿██代孕选性别生男孩 ██试管包出生██代孕男孩██代孕包出生███代孕选性别██试管婴儿███代孕生男孩█████试管婴儿代孕生男孩███供卵试管婴儿代孕███

前言

当前Android的路由库实在太多了,刚开始的时候想为什么要用路由表的库,用Android原生的Scheme码不就好了,又不像iOS只能类依赖,后面越深入就越发现当时想的太简单了,后面看到Retrofit和OKHttp,才想到页面请求本质和网络请求不是一样吗,终于业界最简单高效的路由方案1.0出来了

OkDeepLink

背景

什么是路由

根据路由表页面请求分发到指定页面

使用场景

  1. App接收到一个通知,点击通知打开App的某个页面
  2. 浏览器App中点击某个链接打开App的某个页面
  3. 运营活动需求,动态把原生的页面替换成H5页面
  4. 打开页面需要某些条件,先验证完条件,再去打开那个页面
  5. 不合法的打开App的页面被屏蔽掉
  6. H5打开链接在所有平台都一样,方便统一跳转
  7. App存在就打开页面,不存在就去下载页面下载,只有Google的App Link支持

为什么要有路由

Android原生已经支持AndroidManifest去管理App跳转,为什么要有路由库,这可能是大部分人接触到Android各种Router库不太明白的地方,这里我讲一下我的理解

  • 显示Intent:项目庞大以后,类依赖耦合太大,不适合组件化拆分
  • 隐式Intent:协作困难,调用时候不知道调什么参数
  • 每个注册了Scheme的Activity都可以直接打开,有安全风险
  • AndroidMainfest集中式管理比较臃肿
  • 无法动态修改路由,如果页面出错,无法动态降级
  • 无法动态拦截跳转,譬如未登录的情况下,打开登录页面,登录成功后接着打开刚才想打开的页面
  • H5、Android、iOS地址不一样,不利于统一跳转

怎么样的路由才算好路由

路由说到底还是为了解决开发者遇到的各种奇葩需求,使用简单、侵入性低、维护方便是首要条件,不影响你原来的代码,写入代码也很少,这里就要说说我的OkDeepLink的五大功能了,五大功能瞬间击中你的各种痛点,早点下班不是梦。

  • 编译时注解,实现静态路由表,不再需要在臃肿的AndroidManifest中找到那个Actvity写Scheme和Intent Filter
  • 异步拦截器,实现动态路由,安全拦截、动态降级难不倒你
  • 模仿Retrofit接口式调用,实现方式用apt,不耗性能,参数调用不再是问题
  • HookOnActivityResult,支持RxJava响应式调用,不再需要进行requestCode判断
  • 参数依赖注入,自动保存,不再需要手动写onSaveInstanceonCreate(SaveInstace)onNewIntent(Intent)getQueryParamer

注册路由

具体使用见OkDeepLink

路由结构图

详细比较

大部分路由库都用Apt(编译时注解)生成路由表,然后用路由表转发到指定页面

方案对比 OkDeepLink Airbnb DeepLinkDispatch 阿里 ARouter 天猫 统跳协议 ActivityRouter
路由注册 注解式接口注册 每个module都要手动注册 每个module的路由表都要类查找 AndroidManiFest配置 每个module都要手动注册
路由查找 路由表 路由表 路由表 系统Intent 路由表
路由分发 Activity转发 Activity转发 Activity转发 Activity转发 Activity转发
动态替换 Rxjava实现异步拦截器 不支持 线程等待 不支持 不支持
动态拦截 Rxjava实现异步拦截器 不支持 线程等待 不支持 主线程
安全拦截 Rxjava实现异步拦截器 不支持 线程等待 不支持 主线程
方法调用 接口 手动拼装 手动拼装 手动拼装 手动拼装
参数获取 Apt依赖注入,支持所有类型,不需要在Activity的onCreate中手动调用get方法 参数定义在path,不利于多人协作 Apt依赖注入,但是要手动调用get方法 手动调用 手动调用
结果返回 Rxjava回调 onActivityResult onActivityResult onActivityResult onActivityResult
Module接入不同App 支持 不支持 支持 不支持 支持

其实说到底,路由的本质就是注册再转发,围绕着转发可以进行各种操作,拦截,替换,参数获取等等,其他Apt、Rxjava说到底都只是为了方便使用出现的,这里你会发现各种路由库反而为了修复各种工具带来的问题,出现了原来没有的问题,譬如DeepLinkDispatch为了解决Apt没法汇总所有Module路由,每个module都要手动注册,ARouter为了解决Apt没法汇总所有Module路由,通过类操作耗时,才出现分组的概念。

原理分析

原理流程图

定义路由

路由定义

我这边是完全按照URL规范了,这里要说一下,现在好多方法是把参数定义在path里面的,虽然这样做,有不需要额外传参数的好处,但是这样路由就没有那么灵活,调试起来就没有那么方便了。
建议有好几款app的公司,host都一样,只有scheme不一样,这样只要替换Scheme就能实现降级,维护也简单。

路由注册

AndroidManifest里面的acitivity声明scheme码是不安全的,所有App都可以打开这个页面,这里就产生有两种方式去注册,

  • 注解产生路由表,通过DispatchActivity转发
  • AndroidManifest注册,将其export=fasle,但是再通过DispatchActivity转发Intent,天猫就是这么做的,比上面的方法的好处是路由查找都是系统调用,省掉了维护路由表的过程,但是AndroidManifest配置还是比较不方便的

我现在还是采用了注解,后面我会结合两种方法,将注解自动修改AndroidManifest,对于接入方是没有变动的,方法已经找到了,用自定义Lint扫描出注解相关的Activity,然后用processManifestTask修改Manifest,有个demo了,后面会接入。

生成路由表

譬如通过Apt把这段代码

public interface SampleService {

    @Path("/main") @Activity(MainActivity.class) void startMainActivity(@Query("key") String key); }

生成

@After("execution(* okdeeplink.DeepLinkClient.init(..))")
  public void init() { DeepLinkClient.addAddress(new Address("/main", MainActivity.class)); }

初始化路由表

这里就要提一下使用Apt会造成每个module都要手动注册

DeepLinkDispatch是这么做的

@DeepLinkModule
public class SampleModule {
}
@DeepLinkHandler({ SampleModule.class, LibraryDeepLinkModule.class })
public class DeepLinkActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); DeepLinkDelegate deepLinkDelegate = new DeepLinkDelegate( new SampleModuleLoader(), new LibraryDeepLinkModuleLoader()); deepLinkDelegate.dispatchFrom(this); finish(); } }

ARouter是通过类查找,就比较耗时了,所以他又加入了分组的概念,按需加载

/**
     * 通过指定包名,扫描包下面包含的所有的ClassName
     *
     * @param context     U know
     * @param packageName 包名
     * @return 所有class的集合
     */
    public static List<String> getFileNameByPackageName(Context context, String packageName) throws PackageManager.NameNotFoundException, IOException { List<String> classNames = new ArrayList<>(); for (String path : getSourcePaths(context)) { DexFile dexfile = null; try { if (path.endsWith(EXTRACTED_SUFFIX)) { //NOT use new DexFile(path), because it will throw "permission error in /data/dalvik-cache" dexfile = DexFile.loadDex(path, path + ".tmp", 0); } else { dexfile = new DexFile(path); } Enumeration<String> dexEntries = dexfile.entries(); while (dexEntries.hasMoreElements()) { String className = dexEntries.nextElement(); if (className.contains(packageName)) { classNames.add(className); } } } catch (Throwable ignore) { Log.e("ARouter", "Scan map file in dex files made error.", ignore); } finally { if (null != dexfile) { try { dexfile.close(); } catch (Throwable ignore) { } } } } Log.d("ARouter", "Filter " + classNames.size() + " classes by packageName <" + packageName + ">"); return classNames; }

ActivityRouter就比较巧妙了,通过Stub项目,其他地方都是provide的,只有主工程里面用Apt生成RouterInit类,虽然还是要写module的注解

        // RouterInit
        if (hasModules) {
            debug("generate modules RouterInit");
            generateModulesRouterInit(moduleNames);
        } else if (!hasModule) {
            debug("generate default RouterInit"); generateDefaultRouterInit(); }

天猫 统跳协议 是最简单的,转发一下Intent就可以,但是这样就没法享受注解的好处了。

而我用aspectj解决了这个问题,会自动汇总所有module的路由省略了这些多余的代码,或者有谁知道用Apt自生怎么解决,请联系我一下。

@After("execution(* okdeeplink.DeepLinkClient.init(..))")
  public void init() { DeepLinkClient.addAddress(new Address("/main", MainActivity.class)); }

路由查找

路由查找就是查找路由表对应的页面,值得提起的就是因为要适应Module接入不同App,Scheme要自动适应,路由表其实是Path—》Activity,这样的话内部跳转的时候ARouterUri是没有的。而我这边是有的,我组装了一个内部的Uri,这样拦截器不会有影响。

public Request buildRequest(Intent sourceIntent) {
        if (sourceIntent == null) { return null; } Intent newIntent = new Intent(sourceIntent); Uri uri = newIntent.getData(); addNewTaskFlag(newIntent); if (uri != null) { addBundleQuery(newIntent, uri); Address entry = new DeepLinkClient(context).matchUrl(uri.toString()); if (entry == null || entry.getActivityClass() == null) { return new Request(newIntent, this).setDeepLink(false); } newIntent.setComponent(new ComponentName(context, entry.getActivityClass())); return new Request(newIntent, this); } return new Request(newIntent, this).setDeepLink(false); }

路由分发

现在所有路由方案分发都是用Activity做分发的,这样做会有这几个缺点

  1. 每次都要启动一个Activity,而Activity就算不写任何代码启动都要0.1秒
  2. 如果是异步等待的话,Activiy要在合适时间finish,不然会有一层透明的页面阻挡操作

对于第一个问题,有两个方法

  1. QQ音乐是把DispatchActivity设为SingleInstacne,但是这样的话,动画会奇怪,堆栈也会乱掉,后退会有一层透明的页面阻挡操作
  2. DispatchActivity只在外部打开的时候调用

我选择了第二种

对于第二个问题,有两个方法

  1. DispatchActivity再把Intent转发到Service,再finish,这种方法唯一的缺陷是拦截器里面的context是Servcie的activity,就没发再拦截器里面弹出对话框了。
  2. DispatchActivity在打开和错误的时候finish,如果activity已经finish了,就用application的context去转发路由

我选择了第二种

  public void dispatchFrom(Intent intent) {
        new DeepLinkClient(this) .buildRequest(intent) .dispatch() .subscribe(new Subscriber<Request>() { @Override public void onCompleted() {

猜你喜欢

转载自www.cnblogs.com/dujiaCC/p/10940186.html