SAF-Kotlin-Router

Introduction: android 路由框架,支持模块化架构
More: Author   ReportBugs   
Tags:

@Tony 沈哲 on weibo License

最新版本

模块 saf-router saf-router-compiler saf-router-annotation
最新版本 Download Download Download

下载安装

在 app 模块目录下的 build.gradle 中添加

dependencies {
    implementation 'com.safframework.router:saf-router:1.2.1'
    implementation 'com.safframework.router:saf-router-annotation:1.2.0'
    annotationProcessor 'com.safframework.router:saf-router-compiler:1.2.0'
    ...
}

特性

  • 早期参考了 rails 框架的 router 功能,它能够非常简单地实现 app 的应用内跳转,包括 Activity 之间、Fragment 之间实现相互跳转,并传递参数。

  • 本框架的 saf-router-compiler、saf-router-annotation 模块是使用kotlin编写的。

  • 从 1.1 版本开始支持模块化的架构。

  • 从 1.2 版本开始,支持对某个类中的某个方法使用路由跳转。

使用方法

1. Activity 跳转

它支持 Annotation 方式和非 Annotation 的方式来进行 Activity 页面跳转。使用 Activity 跳转时,必须在 App 的 Application 中做好 router 的映射。

我们会做这样的映射,表示从某个 Activity 跳转到另一个 Activity 需要传递 user、password 这 2 个参数

Router.getInstance().setContext(getApplicationContext()); // 这一步是必须的,用于初始化 Router
Router.getInstance().map("user/:user/password/:password", DetailActivity.class);

有时候,activity 跳转还会有动画效果,那么我们可以这么做

RouterOptions options = new RouterOptions();
options.enterAnim = R.anim.slide_right_in;
options.exitAnim = R.anim.slide_left_out;
Router.getInstance().map("user/:user/password/:password", DetailActivity.class, options);

1.1 Annotation 方式

在任意要跳转的目标 Activity 上,添加@RouterRule,它是编译时的注解。

@RouterRule(url={"second/:second"})
public class SecondActivity extends Activity {

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

        Intent i = getIntent();
        if (i!=null) {
            String second = i.getStringExtra("second");
            Log.i("SecondActivity","second="+second);
        }
    }
}

而且,使用@RouterRule也支持跳转的动画效果。

用 Annotation 方式来进行页面跳转时,Application 无需做 router 的映射。因为,saf-router-compiler 模块已经在编译时生成了一个 RouterManager 类,它大概是这样的:

package com.safframework.router;

import android.content.Context;
import com.safframework.activity.SecondActivity;
import com.safframework.router.RouterParameter.RouterOptions;

public class RouterManager {
  public static void init(Context context) {
    Router.getInstance().setContext(context);
    RouterOptions options = null;
    Router.getInstance().map("second/:second", SecondActivity.class);
  }
}

Application 中只需做一句话的调用:

RouterManager.init(this);// 这一步是必须的,用于初始化 Router

1.2 非 Annotation 方式

在 Application 中定义好 router 的映射之后,activity 之间跳转只需在 activity 中写下如下的代码,即可跳转到相应的 Activity,并传递参数

Router.getInstance().open("user/fengzhizi715/password/715");

2. Fragment 跳转

Fragment 之间的跳转无须在 Application 中定义跳转的映射。可以直接在某个 Fragment 写下如下的代码

Router.getInstance().openFragment(new FragmentOptions(getFragmentManager(),new Fragment2()), R.id.content_frame);

当然在 Fragment 之间跳转可以传递参数

Router.getInstance().openFragment("user/fengzhizi715/password/715",new FragmentOptions(getFragmentManager(),new Fragment2()), R.id.content_frame);

3. 其他跳转

单独跳转到某个网页,调用系统电话,调用手机上的地图 app 打开地图等无须在 Application 中定义跳转映射。

Router.getInstance().openURI("http://www.g.cn");

Router.getInstance().openURI("tel://18662430000");

Router.getInstance().openURI("geo:0,0?q=31,121");

4. 模块化

1.1.0 版本之后新增了@Module 和@Modules 注解为了支持模块化的架构。

模块化架构需要注意:

  • 每个使用了 @RouterRule 的 module 都要添加 annotationProcessor/kapt 依赖
  • 每个 module(包含主模块) 都要添加一个 @Module(name) 的注解在任意类上面,name 是模块的名称
  • 主项目要添加一个 @Modules({name0, name1, name2}) 的注解,指定所有的 module 名称集合

使用模块化架构时,在 app 模块中 saf-router-compiler 会编译时生成了一个 RouterManager 类,它大概是这样的:

package com.safframework.router;

import android.content.Context;

public final class RouterManager {
  public static void init(Context context) {
    Router.getInstance().setContext(context);
    RouterMapping_ 模块 1.map();
    RouterMapping_ 模块 2.map();
    ...
  }
}

除了生成一个唯一的 RouterManager 类之外,每一个模块还会生成一个RouterMapping_ 模块名的类。该类包含了这个模块的路由表。

package com.safframework.router;

public final class RouterMapping_main {
  public static void map() {
    RouterOptions options = null;
    Router.getInstance().map("main/main", MainActivity.class);
    Router.getInstance().map("main/guide", GuideActivity.class);
    ...
  }
}

5. 支持 Kotlin 项目

对于 Kotlin 的项目或者 Activity 使用 Kotlin 来编写的,需要在 module 目录下的 build.gradle 中添加

apply plugin: 'kotlin-kapt'

...

dependencies {
    implementation 'com.safframework.router:saf-router:1.2.0'
    implementation 'com.safframework.router:saf-router-annotation:.2.0'
    kapt 'com.safframework.router:saf-router-compiler:1.2.0'
    ...
}

注意此时,apply plugin: 'com.neenbedankt.android-apt' 无需再使用了。

6.降级策略

Router 新增了一个方法 setErrorActivity(), 可以设置一个自定义的全局错误的 Activity,如果路由服务找不到对应的 Activity 则跳转到这个 errorActivity,防止 app 引起 crash,所以说它是一种简单的降级策略。

关键方法

函数 作用
map 路由服务的映射,将 app 页面跳转的过程映射成 path,存放在 Router 的路由表中
openURI 调用系统服务打开网页、打电话、调用地图 app
open 跳转到某个 activity 并传值
openForResult 跳转到某个 activity 并传值,使用 startActivityForResult 进行跳转
openFragment 跳转到某个 Fragment
setErrorActivity 设置自定义的全局的 Error Activity,如果路由服务找不到相应的 Activity,则跳转到该 Error Activity

TODO:

  1. 更优雅的 API

License

Copyright (C) 2017 - present Tony Shen.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

   http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
Apps
About Me
GitHub: Trinea
Facebook: Dev Tools