前言:这篇模块化与组件化的文章,用2篇文章介绍。可能有些人以为网上已经有了文章,为何还要写。第一:为了记录本身的正常也算当作笔记。第二:网上当然有好文,但最近看了一篇竟然有150多赞,可是介绍的迷迷糊糊,不少知识点略过。本文重点是让你快速入门,理解以及使用。java
本次模块化/组件化讲解总共分2篇(必须先了解ARouter,或第三方路由框架):
一、阿里路由框架ARouter的基本使用
二、Android中经过对gradle的管理实现组件化;并配合ARouter,随意跳转切换android
这里为何会使用路由框架呢,为了让模块之间相互通讯,好比你你项目 引入Module A。同时引入了 Module B。项目能够同时访问A和B。但此时A要访问B,B要访问A怎么办呢。这时候就须要路由框架去解决了。这只是一方面而已。git
首先放上ARouter的github地址
app build.gradle的dependencies标签加上github
implementation 'com.alibaba:arouter-api:1.3.1'
annotationProcessor 'com.alibaba:arouter-compiler:1.1.4'
复制代码
在android标签下的defaultConfig加上javaCompileOptions:api
android {
compileSdkVersion 28
defaultConfig {
...
javaCompileOptions {
annotationProcessorOptions {
arguments = [moduleName: project.getName()]
}
}
}
}
复制代码
在application里初始化,记得在发布线上版本,要日志和debug关闭,代码以下:app
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);
}
}
复制代码
在咱们使用的Activity或Fragment里。使用@Route标注,且path = "/x/y",x为包名(取最后一位便可),y为当前类名:ide
@Route(path = "/myapplication/MainActivity")
public class MainActivity extends BaseActivity {
}
复制代码
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();
复制代码
只需在后面.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()
String name;
复制代码
@Autowired(name = "age")
int mAge;
复制代码
mPerson = (Person) getIntent().getSerializableExtra("human");
复制代码
以前咱们要带动画跳转,要用到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,不支持新版动画");
}
复制代码
也是在.navigation()里,只要带上requestCode就Ok了。而后onActivityResult和正常使用同样。
ARouter.getInstance()
.build(Constance.ACTIVITY_PATH_SIMPLE)
.navigation(Context context, int requestCode);
复制代码
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();
复制代码
之间说了Activity和Fragment都须要用@Route标注加上path。 这里Fragment的使用和Activity同样,但惟一的区别是,Activity是跳转,而Fragment是实例化Fragmen的实例,以下:
//记得要强转一下,这里传值什么的和Activity的用法同样。
HomeFragment homeFragment = (HomeFragment)ARouter.getInstance().build(Constance.Fragment_PATH_SIMPLE).navigation();
复制代码
咱们先看一段拦截器的代码:
@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");
}
}
复制代码
一、拦截器使用很奇特,只要在你代码里写上这个类,就起做用了。估计@Interceptor标注,apt帮咱们干了很多事。
二、首先用@Interceptor标注,(priority = 1)优先级,越小,越先执行。
三、实现IInterceptor接口。实现2个方法:init(),process()。
四、init()方法,在项目启动时候首先执行,process()方法在Activity跳转时调用
五、若是咱们要为拦截器加上一些帅选条件的话能够经过Postcard
六、注意,只要设置了拦截器,这里不调用callback.onContinue(postcard);就会卡在当前的拦截器内。固然跳转就卡在当前页面。
直接上代码。在代码里注释
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");
}
});
复制代码