不怕跌倒,所以飞翔

参考文献:
superxlcr的ARouter学习笔记
码字农民工的文章
繁华落尽666的文章

本文主要介绍的知识点

  • 关于android路由框架解决的问题
  • android路由框架的使用(这里只是介绍ARouter的使用)
  • 关于使用ARouter框架的注意事项
  • 总结

1.Android路由框架解决的问题

相信大家在工作中都会遇到这样的问题,通过其他App或者通过网页跳转到指定的自己的App或者跳转到指定的页面中去,一般都是在推送中或者通过Banner点击之后的操作,一般的操作都是像下面这样的

  • 设置相应的intent-filter
        
  • 通过Intent隐式跳转到相应的Activity
    Intent intent = new Intent();    intent.setAction("com.hejin.arouter.Main2Activity");    startActivity(intent);

其实这里我要说明一下,如果你是正规的开发公司我觉得一般都不会这么去写,其实这个跳转完全能实现,但是一般正规的公司都会定一些协议和端口号,也就是说会添加scheme来指定一些数据的协议部分和path进行匹配,但是随着时间的推移和团队的扩大,会慢慢的暴露出很多问题:

  • 集中式的URL管理:谈到集中式的管理,总是比较蛋疼,多人协同开发的时候,大家都去AndroidManifest.xml中定义各种IntentFilter,使用隐式Intent,最终发现AndroidManifest.xml中充斥着各种Schame,各种Path,需要经常解决Path重叠覆盖、过多的Activity被导出,引发安全风险等问题
  • 可配置性较差:Manifest限制于xml格式,书写麻烦,配置复杂,可以自定义的东西也较少
  • 跨模块无法显式依赖:在App小有规模的时候,我们会对App做水平拆分,按照业务拆分成多个子模块,之间完全解耦,通过打包流程控制App功能,这样方便应对大团队多人协作,互相逻辑不干扰,这时候只能依赖隐式Intent跳转,书写麻烦,成功与否难以控制。

尤其是在项目演进的时候都会进行组件化开发,所以这里网上有很多大神就研究出路由框架这么一个东西,解决了上面的相应问题,这里接触的就是阿里巴巴开源的ARouter在GitHub上已经已经有3.+k的start了,相对来说应该比较稳定,所以让我们开始吧!

2.ARouter的简单使用

2.1首先是把ARouter引入到项目中去

  • 首先在在module中配置相应的参数
    defaultConfig {        .......        javaCompileOptions {            annotationProcessorOptions {                arguments = [ moduleName : project.getName() ]            }        }    }
  • 然后配置api和compiler(这个也是在module中)
dependencies {    compile 'com.alibaba:arouter-api:x.x.x'    annotationProcessor 'com.alibaba:arouter-compiler:x.x.x'    ...}
  • 上面是github上面写的内容,但是有一点他没有写,但是就是一定要在项目的gradle中添加下面这段代码:
    dependencies {        classpath 'com.android.tools.build:gradle:2.3.3'        classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8' //路由需要        // NOTE: Do not place your application dependencies here; they belong        // in the individual module build.gradle files    }

这句话一定要加上否则根本就跳转不过去,具体为什么我还真是不知道....
有了以上的内容就完成了基本的配置,就可以进行相应的跳转了...

2.2代码中的简单使用

  • 在Application中初始化ARouter
        /*初始化路由框架*/        ARouter.init(this);
  • 首先要在你要跳转的Activity(或者说是目标的Activity)添加注释
@Route(path = "XXX/XXX")

这里面要注意两点首先这个注解里面的内容必须是二级菜单,这个在github上面有解释,其次就是这个注解要写在Activity的类上边

  • 通过代码进行跳转(发起路由)
ARouter.getInstance().build("/XXX/XXX").navigation();//跳转中携带参数ARouter.getInstance().build("/XXX/XXX")             .withLong("key", "value")             .withString("key", "value")             .navigation

这里面的参数要和你要跳转的Activity注解中的参数保持一致,当你传递参数的时候,你直接通过Intent去取就可以了.

通过以上步骤就能实现基本的跳转传递参数了,但是身为有逼格的程序员我们怎么能这样就满足了呢?

3.ARouter进阶使用

3.1 利用Uri进行跳转

        Uri uri = Uri.parse("/test/activity");        ARouter.getInstance()                .build(uri)                .navigation();

3.2传递参数的获取问题

当你传递参数的时候你可以通过Intent取获取,当然也可以通过相应的注解进行获取,就像下面这样:

@Autowired(name = "xxx")public String text;

这里呢要注意,修饰符必须是public并且key值要相互对应.还要在目标的Activtiy中添加ARouter.getInstance().inject(this);才可以使用相应的值,否则取值的时候会失败,但是不会报空指针.

3.3关于转场动画的跳转处理

有没有想过,之前在Activity跳转的时候可以使用overridePendingTransition();,但是现在通过路由跳转的话,没有地方取设置动画了,然后ARouter为我们想到了这个问题.

  • 旧动画:使用withTransition方法即可(相当于之前的overridePendingTransition()方法设置)
ARouter.getInstance().build(path).withTransition(R.anim_slide_in,R.anim_slide_out);
  • 新动画:使用withOptionsCompat方法即可(Android5.0新出的转场动画)
ActivityOptionsCompat compat = ActivityOptionsCompat.                  makeScaleUpAnimation(view, view.getWidth() / 2, view.getHeight() / 2, 0, 0);    ARouter.getInstance().build("path").withOptionsCompat(compat)                  .navigation();  

3.4ARouter处理跳转过程的结果

ARouter可以让我们处理跳转过程的结果,什么用呢?就是你找到目标之后要进行什么操作.

ARouter.getInstance().build("/module/jumpTestActivity2").navigation(null,          new NavigationCallback() {              @Override              public void onFound(Postcard postcard) {                  // 找到目标后进行的操作              }                @Override              public void onLost(Postcard postcard) {                  // 找不到目标进行的操作              }          });  

补充说明:
在最新api中已经是四个方法了!

        ARouter.getInstance().build("/test/activity").navigation(this, new NavigationCallback() {            @Override            public void onFound(Postcard postcard) {        //找到队应的内容的时候                Log.e("done", "onFound: ");            }            @Override            public void onLost(Postcard postcard) {        //没有找到对应的内容的时候                Log.e("done", "onLost: ");            }            @Override            public void onArrival(Postcard postcard) {        //跳转成功                Log.e("done", "onArrival: ");            }            @Override            public void onInterrupt(Postcard postcard) {        //拦截操作                Log.e("done", "onInterrupt: ");            }        });

这里可以在onLost中去处理"位置页面"的跳转结果,比如升级APP之类的话术.

3.5携带结果的Activity

ARouter.getInstance().build("/test/activity").navigation(this,10);

后面那个参数就是请求码,别的和之前的都一样.

3.6组的概念

在ARouter中有个组的概念,什么意思呢?就是在构建路由请求的时候,可以指定分组.
其实这个分组本来就是有个你像path=/test/activity test就相当是分组,但是也可以使用group进行分组,像下面这段代码:

@Route(path = "/test/activity", group = "app")

这里需要强调一下,如果你设置了相应的分组,那么在进行跳转的时候,一定要使用ARouter.getInstance().build(path, group)进行跳转,否则无法找到相应的跳转

3.7重写跳转URL实现重定向

可以重新定向你的URL地址

@Route(path = "/test/activity2")public class PathReplaceServerImp implements PathReplaceService {    @Override    public String forString(String path) {        path = "/test/activity2";        return path;    }    @Override    public Uri forUri(Uri uri) {        return null;    }    @Override    public void init(Context context) {        Log.e("done", "init: 这里是初始化的时候执行的方法");    }}

这里说明一下:上面得path一定要加上一个任意项目中出现得注解即可,如果项目中没有出现得话会报空指针异常的.通过上面的代码,就可以更改项目中跳转时候的path和URL地址了.

3.8ARouter拦截器

ARouter的拦截器可以在navigation的过程中拦截请求,并进行一系列的处理 ,是一种AOP的编程模式(应用场景为检查登陆状态等)要实现拦截器,首先我们需要实现IInterceptor接口,并使用Interceptor注解标记我们的拦截器,并传入priority优先级参数(数字越小,优先级越高),其实拦截器就是实现了一个接口去进行回调的!

public class TestInterceotor implements IInterceptor {    @Override    public void process(Postcard postcard, final InterceptorCallback callback) {        if (postcard.getPath().equals("/test/activity")) {            callback.onContinue(postcard);        } else {            callback.onContinue(postcard);        }    }    @Override    public void init(Context context) {        Log.e("done", "init: 初始化调用");    }}

这里说明几点内容:

  • 首先process这个方法是处理拦截内容的,这里我判断了一个相应的注解路由,如果跳转的是相应的路径,那么进行拦截.
  • 其次callback.onContinue(postcard)这个要注意,这句话的含义就是交由路由去处理,如果这里不写这句话的话,路由就终止了.
  • init方法是全局只执行一次,这里为什么这么设计我也不知道,应该是用到相应的内容了吧!原谅我是一个菜鸟
  • 如果你想加入相应的等级的话在类的上面加入如下注解@Interceptor(priority = 7)其实就是设置拦截器等级的,这里为什么又拦截器的等级呢?主要是为了让拦截器一级一级的向下传递.这样就有了多级的拦截器.

上面的内容只是简单的用到了拦截器,但是理解起来毕竟又一些晦涩,当直接说让你实现登陆的拦截,你怎么实现,开始的时候我也觉得简单,但是当自己写的时候,我发现这个问题真不是看上去那么简单.这里我先把内容拦截器的代码都放上,然后我在讲解!

  • 首次跳转的逻辑
        ARouter.getInstance().build("/test/activity").navigation(this, new NavCallback() {            @Override            public void onArrival(Postcard postcard) {            }            @Override            public void onInterrupt(Postcard postcard) {                Log.e(TAG, "onInterrupt: 这个方法是拦截器执行之后才执行的");            }        });
  • 拦截器的代码:
@Interceptor(priority = 7)public class TestInterceotor implements IInterceptor {    @Override    public void process(Postcard postcard, final InterceptorCallback callback) {        if (postcard.getPath().equals("/test/activity")) {            Log.e("done", "process: main2Activity");            if (APP.isLogin) {/*已经登陆*/                callback.onContinue(postcard);            } else {/*没有登陆*/                ARouter.getInstance().build("/test/activity2")                        .withString("name", postcard.getPath()).navigation();            }            Log.e("done", "process: 执行完了");        } else {            Log.e("done", "process: 这个方法什么时候执行");            callback.onContinue(postcard);        }    }    @Override    public void init(Context context) {        Log.e("done", "init: 初始化调用");    }}
  • 模拟登陆的Activity
@Route(path = "/test/activity2")public class Main3Activity extends AppCompatActivity {    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main3);        ARouter.getInstance().inject(this);    }    public void click(View view) {        APP.isLogin = true;        ARouter.getInstance().build("/test/activity").navigation();        finish();    }}

这里第一次跳转的时候,由于拦截器使得没有登陆的逻辑就跳转到了登陆页面,之后我在登陆页面模拟了一次登陆的操作,然后关闭这个页面之前,我又重新跳转了目标页面,这次由于已经登陆了,所以会直接继续执行跳转了目标页面.这里说的挺简单的,有一个回调我还没有搞清楚,onInterrupt这个回调之后有什么用,其实这里也可以传入一个字段,然后跳转的时候直接传入这个字段,这个字段主要是保存要跳转的页面的数据,之后就能直接跳转了.这样就解决了耦合的问题.

3.9在拦截器中添加额外的参数

@Route(path = "/test/activity", extras = 0;/*注意这里是int类型的参数*/)

说明一下:这个是在目标的Activity页面添加的额外参数,之后会在拦截器内生效.

总结

其实关于这个框架还有很多问题我没有理解,但是基本的一些内容都已经讲解了,其实接触这个框架主要是当初看见组件化开发的时候,看到了这个框架,其实在项目中使用也可以,整体管理了跳转.写的挺乱的,感谢大家抽出宝贵时间来阅读,有什么不对的地方希望指正.

更多相关文章

  1. Android(安卓)手把手教你写EventBus
  2. Android(安卓)Lua 相互调用
  3. 快速理解android View的测量onMeasure()与MeasureSpec
  4. Android面试整理(2016)
  5. Android常用功能实例----(十一)小功能(获取IMEI|手机号等)
  6. Android中使用OkHttp框架
  7. 闹钟
  8. 自定义Android注解Part3:绑定
  9. Activity之间的相互调用与传递参数

随机推荐

  1. Android使用FFMPEG将H264解码为yuv420p
  2. Android View.startAnimation()动画
  3. Android 手机QQ临时会话
  4. Android 中使用 ComponentName 类
  5. 如何让TextView自己滚动
  6. Android(安卓)Studio 1.3.0 以上gradle p
  7. Android 利用PdfDocument产生PDF文档
  8. [Android] 调用相机、打开相册、裁剪图片
  9. Android中Environment,context获取路径
  10. Android音视频处理之MediaMuxer