组件化/模块化的快速入门及使用之:阿里路由框架ARouter的基本使用。

前言:这篇模块化与组件化的文章,用2篇文章介绍。可能有些人觉得网上已经有了文章,为什么还要写。第一:为了记录自己的正常也算当做笔记。第二:网上固然有好文,但最近看了一篇居然有150多赞,但是介绍的迷迷糊糊,很多知识点略过。本文重点是让你快速入门,理解以及使用。

本次模块化/组件化讲解总共分2篇(必须先了解ARouter,或第三方路由框架):
1、阿里路由框架ARouter的基本使用
2、Android中通过对gradle的管理实现组件化;并配合ARouter,随意跳转切换

这里为什么会使用路由框架呢,为了让模块之间相互通信,比如你你项目 引入Module A。同时引入了 Module B。项目可以同时访问A和B。但此时A要访问B,B要访问A怎么办呢。这时候就需要路由框架去解决了。这只是一方面而已。

1、添加依赖

首先放上ARouter的github地址

app build.gradle的dependencies标签加上

 implementation 'com.alibaba:arouter-api:1.3.1'
 annotationProcessor 'com.alibaba:arouter-compiler:1.1.4'


在android标签下的defaultConfig加上javaCompileOptions:

android {
    
    
    compileSdkVersion 28
    defaultConfig {
    
    
        ...
        javaCompileOptions {
    
    
            annotationProcessorOptions {
    
    
                arguments = [moduleName: project.getName()]
            }
        }

    }
    
}

2、初始化

在application里初始化,记得在发布线上版本,要日志和debug关闭,代码如下:

public class MyApplication extends Application {
    
    
    //ARouter 调试开关
    private boolean isDebugARouter = true;

    @Override
    public void onCreate() {
    
    
        super.onCreate();
        context = this;
        if (isDebugARouter) {
    
    
            //下面2行必须卸载ARouter init 之间,否则无效
            //打印日志
            ARouter.openLog();
            //开启调试模式(如果在InstantRun的模式下必须开启,线上必须关闭)
            ARouter.openDebug();
        }

        // 官方建议在Application中初始化
        ARouter.init(this);
    }

    @Override
    public void onTerminate() {
    
    
        super.onTerminate();
        ARouter.getInstance().destroy();
    }

}


同时ARouter的使用有点像Dagger2,需要调用ARouter.getInstance().inject(Object obj);我们把他封装在Base里:

public abstract class BaseActivity extends AppCompatActivity {
    
    
    //省略部分代码,便于理解
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
    
    
        super.onCreate(savedInstanceState);
        setContentView(getContentViewId());
        ARouter.getInstance().inject(this);
    }
}

3、@Route的使用

在我们使用的Activity或Fragment里。使用@Route标注,且path = “/x/y”,x为包名(取最后一位即可),y为当前类名:

@Route(path = "/myapplication/MainActivity")
public class MainActivity extends BaseActivity {
    
    
    
}

4、ARouter里Activity之间的跳转

Activity与Activity里的跳转只需调用如下代码,build里的路径,就是我们用标注@Route path标注的路径:

ARouter.getInstance().build("/myapplication/MainActivity").navigation();

从上面代码我们发现。路径"/myapplication/MainActivity",得统一用个常量类管理起来,不然这样找起来,简直费事,如下:

public final class Constance {
    
    
    public static final String ACTIVITY_PATH_MAIN = "/myapplication/MainActivity";
}


这里除了路径跳转外,从他的参数类型中,还能看到有Uri跳转:

        Uri uri = Uri.parse(Constance.ACTIVITY_PATH_MAIN);
        ARouter.getInstance().build(uri).navigation();

5、带参数跳转 & 获取参数

带参数跳转

只需在后面.withString(),即可,里面包含了所有你想传的类型

ARouter.getInstance()
                .build("/myapplication/MainActivity")
                .withString("name", "lihang")
                .withInt("age", 27)
                .withSerializable("human", new Person("力哈", "11"))
                .navigation();

获取参数

在获取参数页面,注意这里有个大坑:

@Route(path = "/myapplication/SimpleActivity")
public class SimpleActivity extends BaseActivity {
    
    
    @Autowired()
    String name;
    @Autowired(name = "age")
    int mAge;
    //    @Autowired(name = "human")这里注意,如果是传Serializable,注解是得不到的。除非是Paceable
    Person mPerson;

    @Override
    public int getContentViewId() {
    
    
        return R.layout.activity_simple;
    }

    @Override
    public void progressLogic() {
    
    
//        mPerson = (Person) getIntent().getSerializableExtra("human");
    }
}

这里获取参数有3种方式:

  • 使用@Autowired标注后,下方的值是之间传值的key。
@Autowired()
String name;
  • 使用@Autowired标注后,name = key,name等于之间传值的key,下方参数名随便定
@Autowired(name = "age")
int mAge;
  • 带序列化这里有些特殊,如果是Parcelable类型,可以用上方的方法获取。但是如果是Serializable类型,却会发现,没办法获取到。但是这里用我们传统的getIntent也能获取到
mPerson = (Person) getIntent().getSerializableExtra("human");

6、带动画跳转

之前我们要带动画跳转,要用到overridePendingTransition(int anim_in,int anim_out);这里也有提供,但是有个大坑哦:

ARouter.getInstance()
                .build(Constance.ACTIVITY_PATH_SIMPLE)
                .withTransition(R.anim.alpha_activity_in, R.anim.alpha_activity_out)
                //navigation里,一定要加上当前的Context,不然动画不起效
                .navigation(MainActivity.this, 99);


同时ARouter也提供了新版动画,但是需要api>= 16才能使用,效果还是很酷炫的:

        if (Build.VERSION.SDK_INT >= 16) {
    
    
            ActivityOptionsCompat compat = ActivityOptionsCompat.
                    makeScaleUpAnimation(btn, btn.getWidth(), btn.getHeight(), 0, 0);
            ARouter.getInstance()
                    .build(Constance.ACTIVITY_PATH_SIMPLE)
                    .withOptionsCompat(compat)
                    .navigation();
        }else {
    
    
            ToastUtils.showToast("api <16,不支持新版动画");
        }

7、类似Activity里的startActivityForResult(Intent intent, int requestCode);

带requestCode跳转

也是在.navigation()里,只要带上requestCode就Ok了。然后onActivityResult和正常使用一样。

ARouter.getInstance()
                .build(Constance.ACTIVITY_PATH_SIMPLE)
                .navigation(Context context, int requestCode);

setResult返回界面,你没看错,就是这么复杂!

        Postcard postcard = ARouter.getInstance().build(Constance.ACTIVITY_PATH_MAIN);
        LogisticsCenter.completion(postcard);
        Class<?> destination = postcard.getDestination();
        Intent intent = new Intent(SimpleActivity.this, destination);
        setResult(1, intent);
        finish();

8、Fragment的使用

之间说了Activity和Fragment都需要用@Route标注加上path。
这里Fragment的使用和Activity一样,但唯一的区别是,Activity是跳转,而Fragment是实例化Fragmen的实例,如下:

//记得要强转一下,这里传值什么的和Activity的用法一样。
HomeFragment homeFragment = (HomeFragment)ARouter.getInstance().build(Constance.Fragment_PATH_SIMPLE).navigation();

9、拦截器的使用

我们先看一段拦截器的代码:

@Interceptor(priority = 1)
public class FirstInterceptor implements IInterceptor {
    
    
    @Override
    public void process(Postcard postcard, InterceptorCallback callback) {
    
    
        if (postcard.getPath().equals(Constance.ACTIVITY_PATH_SIMPLE)){
    
    
            LogUtils.i("ARouter拦截器", "FirstInterceptor 开始拦截 ======");
        }
        callback.onContinue(postcard);
    }
    @Override
    public void init(Context context) {
    
    
        LogUtils.i("ARouter拦截器", "first init");
    }
}

1、拦截器使用很奇特,只要在你代码里写上这个类,就起作用了。估计@Interceptor标注,apt帮我们干了不少事。

2、首先用@Interceptor标注,(priority = 1)优先级,越小,越先执行。

3、实现IInterceptor接口。实现2个方法:init(),process()。

4、init()方法,在项目启动时候首先执行,process()方法在Activity跳转时调用

5、如果我们要为拦截器加上一些帅选条件的话可以通过Postcard

6、注意,只要设置了拦截器,这里不调用callback.onContinue(postcard);就会卡在当前的拦截器内。当然跳转就卡在当前页面。


10、跳转时加监听,配合拦截器使用

直接上代码。在代码里注释

        ARouter.getInstance()
                .build(Constance.ACTIVITY_PATH_SIMPLE)
                .navigation(MainActivity.this, new NavigationCallback() {
    
    
                    @Override
                    public void onFound(Postcard postcard) {
    
    
                        //路由目标被发现时调用(Activity执行跳转代码,第一个执行)
                        //group 为路径的组。如果不自定义,会默认成path的/x/y的x
                        //group 可以自定义,如:@Route(path = Constance.ACTIVITY_PATH_MAIN,group = Constance.GROUP_FIRST)
                        //当然自定义组之后,跳转的时候要带上组名。
                        String group = postcard.getGroup();
                        //path 为全路径@Route(path = Constance.ACTIVITY_PATH_MAIN)
                        String path = postcard.getPath();
                        LogUtils.i("ARouter拦截器", "onFound ------>  group == " + group + "    " + "path == " + path);
                    }

                    @Override
                    public void onArrival(Postcard postcard) {
    
    
                        //路由到达后调用(注意这里是所有拦截器执行完之后才会调用)
                        String group = postcard.getGroup();
                        String path = postcard.getPath();
                        LogUtils.i("ARouter拦截器", "onArrival ------>  group == " + group + "    " + "path == " + path);
                    }

                    @Override
                    public void onLost(Postcard postcard) {
    
    
                        //路由被丢失时调用
                        LogUtils.i("ARouter拦截器", "onLost");
                    }

                    @Override
                    public void onInterrupt(Postcard postcard) {
    
    
                        //路由被拦截时调用
                        LogUtils.i("ARouter拦截器", "onInterrupt");

                    }

                });

结束语:ARouter的使用就是这样。目前在疯狂学习中。有志同道合或者想跟我一起学习的请加QQ群:209010674。也是为明年有更好的出入准备着。如果也对你有帮助,给我个赞,给我鼓励把。

猜你喜欢

转载自blog.csdn.net/leol_2/article/details/100700079