Android-ARouter

我们上一篇文章是自定义Router,没有看过的小伙伴自定义Router,但今天我们来看一看世面上主流的路由框架-由阿里推出的ARouter.。
参考资料:
https://mp.weixin.qq.com/s/hUKEOp3qa4C53F6ZmPuXjQ
https://mp.weixin.qq.com/s/UljVdlGQuwooVEJz_rctjw

1.项目引入

  • 1.1首先在app的buildgradle添加以下依赖和配置:
    配置在defaultConfig:
  /* ARouter的配置*/
        javaCompileOptions {
            annotationProcessorOptions {
                arguments = [AROUTER_MODULE_NAME: project.getName()]
            }
        }

依赖版本:

//ARouter的依赖
    implementation 'com.alibaba:arouter-api:1.3.1'
    annotationProcessor 'com.alibaba:arouter-compiler:1.2.0'
  • 1.2 代码初始化
public class BaseApplication extends Application {
    //是否开启调试
    private static boolean isDebug =true;
    @Override
    public void onCreate() {
        super.onCreate();
       //必须在初始化之前写入这两行
        if (isDebug) {
            //打印日志
            ARouter.openLog();
            //开始调试
            ARouter.openDebug();
        }
        //ARouter的实例化
        ARouter.init(this);
    }
}

2.常见功能实现

2.1 Activity的跳转

2.1.1 Activity的普通跳转

通常我们都是用startActivity()来进行Activtiy的跳转,我们今天试试路由如何实现。
比如我们的MainActivity要跳转到LoginActivity,那么我们就需要在支持路由的页面上添加注解,如下:

image.png

这个path的值可以理解如果要跳转LgoinActivity,告诉对方它的位置。
注意:路径至少需要两个级别:/ xx / xx

那我们MainActivity点击跳转的代码如下:


image.png

这样就可以实现Activity的跳转了,但我们平时在开发中通常会自定义一个常量类来管理Path,如下:

public class Constants {

    //loginActivity的path
public static final String LOGINPATH="/app/login";
   //MainActivity的path
public static final String MAINPATH="/app/main";

}

所以我们之前的代码就可以替换为:


image.png
 ARouter.getInstance().build(Constants.LOGINPATH).navigation();
2.1.2 Activity通过Uri的跳转

刚才的代码可以这样写:


image.png
2.1.3 Fragement的跳转

Fragment的跳转和Activity相似,先强转在跳转,如:
Fragment fragment = (Fragment) ARouter.getInstance().build(Constance.ACTIVITY_URL_FRAGMENT).navigation()

2.2 Activity的跳转携参

首先我们需要在Activity的setContentView()方法后进行依赖注入(这个注入可以提取的Base中):
ARouter.getInstance().inject(this);
那么我们如何携参跳转呢:主要是withxxx()方法,如下:

image.png

那我们看看目标界面如何接收数据?
目标界面主要通过使用Autowired注解接受数据,如下:

image.png

直接打印即可:
Log.e(TAG,name+age+userBean.getUserMessage());
注意:
只有当@Autowired(name = "key"),也就是key标签一致的情况下,才可以获取到对象的值,所以为了规避每一个可能会遇到的风险,建议在@Autowired里面 都写上与之对应具体的key名

2.3 ARouter之拦截器

2.3.1首先我们自定义拦截器,先implements IInterceptor .

image.png

我们来分析一下这个拦截器,首先要实现个方法:

  • process() ,中断路由进程
  • init() ,拦截器初始化,此方法在sdk初始化时调用,只调用一次

还有Interceptor类注解里的priority即优先级:


image.png

priority这个优先级的数值越小,越先执行,优先级越高值越大,(四大组件中的广播,优先级的取值是-1000到1000,数值越大优先级越高)。如果两个拦截器的优先级一样,项目编译就会报错。所以,不同拦截器定义的优先级属性值不能相同。

ok,我们现在来看一眼代码:

 btnJumpLogin.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                
               Uri uri =Uri.parse(Constants.LOGINPATH);
               ARouter.getInstance().build(uri)
                        .withString("name","张三") //传String
                        .withInt("age",20)//传Int
                         .withParcelable("userbean",new UserBean("家住大城市铁岭"))
                        .navigation(MainActivity.this, new NavigationCallback() {
                            @Override
                            public void onFound(Postcard postcard) {
                                //路由目标被发现时调用
                                Log.e(TAG, "路由目标被发现时调用" );
                            }

                            @Override
                            public void onLost(Postcard postcard) {
                             //路由被丢失时调用
                                Log.e(TAG, "路由被丢失时调用" );
                            }

                            @Override
                            public void onArrival(Postcard postcard) {
                            //路由到达之后调用
                                Log.e(TAG, "路由到达之后调用" );
                            }

                            @Override
                            public void onInterrupt(Postcard postcard) {
                                //路由被拦截时调用
                                Log.e(TAG, "路由被拦截时调用" );
                            }
                        });
            }
        });

咦,怎么多了个NavigationCallback回调接口?它跟拦截器有什么联系呢?
我们运行一下看看打印信息:

image.png

问题出现了:我在点击跳转按钮后,并没有跳转到LoginActivity的页面。
想必同志们也猜测到了:就是我们自定义的拦截器process的方法拦截了这次跳转请求。
那该如何处理呢?我还想继续跳转到LoginActivity页面?


image.png

我们再次打印信息:


image.png

我们现在也可以解答NavigationCallback接口的回调接口了。也就是我们注释的含义:


image.png
2.3.2 NavigationCallback 和 IInterceptor的组合使用

通常我们在开发中会在每个接口里判断用户的是否进行了登陆即登陆后的cookie是否失效之类。那我们如何运用ARouter进行判断呢?
首先我们需要自定义一个NavigationCallback 。

public class CustomNavigationCallback implements NavigationCallback {
    private static final String TAG = "CustomNavigationCallbac";

    Context mContext;

    public CustomNavigationCallback(Context mContext) {
        this.mContext = mContext;
    }

    @Override
    public void onFound(Postcard postcard) {
        //路由目标被发现时调用
        Log.e(TAG, "路由目标被发现时调用" );
    }

    @Override
    public void onLost(Postcard postcard) {
        //路由被丢失时调用
        Log.e(TAG, "路由被丢失时调用" );
    }

    @Override
    public void onArrival(Postcard postcard) {
//路由到达之后调用
        Log.e(TAG, "路由到达之后调用" );
    }

    @Override
    public void onInterrupt(Postcard postcard) {
        //路由被拦截时调用
        Log.e(TAG, "路由被拦截时调用" );
    }
}

其次我们定义一个简单的基类Activity,做一个简单的封装

public abstract class BaseActivity extends AppCompatActivity {

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        if(setLayoutId() != 0){
            setContentView(setLayoutId());
            ARouter.getInstance().inject(this);
            initView();
            initData();
        }
    }

    /**
     * 不带参数跳转
     * @param context
     * @param path
     */
    public static void toActivity(final Context context, String path) {
        ARouter.getInstance().build(path).navigation(context, new CustomNavigationCallback(context));
    }

    /**
     * 带参数跳转
     * @param context
     * @param path
     * @param bundle
     */
    public static void toActivity(final Context context, String path, Bundle bundle) {
        ARouter.getInstance().build(path)
                .withBundle("data", bundle).navigation(context, new CustomNavigationCallback(context));
    }


    public abstract  int setLayoutId();
    public abstract  void initView();
    public abstract  void initData();
}

到此我们还要先定义一个策略,控制是否页面需要登陆,进而在判断是否已经进行了登陆。


image.png

以MainActivity界面为例,如果我们需要MainActivity界面登陆那么可以这样写:


image.png

CustomInterceptor核心代码如下:


image.png

在CustomNavigationCallback的onInterrupt方法中,我们简单toast一下:


image.png

2.4 ARouter实现StartActivityForResult()?

  • 第一步,现在MainActivity重写onActivityResult().
btnStartActivity.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                ARouter.getInstance().build(Constants.LOGINPATH).navigation(MainActivity.this,123,new CustomNavigationCallback(MainActivity.this));
            }
        });

   @Override
    protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
        super.onActivityResult(requestCode, resultCode, data);

        switch (resultCode){
            case 456:
                tvShow.setText("接受到的数据是:"+data.getStringExtra("data"));
                break;
        }
    }
  • 第二步,在LoginActivity的setRuslt()

        Intent mIntent =new Intent().putExtra("data","456");
        setResult(456,mIntent);
        finish();

过于简单我就不解释了。
demo以上传Github,点我传送
基本就这样,好多用法自己去看文档,看不懂英文有中文的,拜拜。

推荐阅读更多精彩内容