Exception from call site #1 bootstrap method
当然,我们配置黄油刀,还需要在Project的build.gradle中配置插件
5.组件的配置
组件的配置在于两方面,一方面是作为依赖,一方面作为一个独立的App
还是先来看下他的build.gradle
[图片上传失败…(image-5b7df3-1607329172143)]
可以看到,这就是他的配置文件,其实很普通,路由和黄油刀的标配,以及添加BaseModule,之后哪怕是添加其他第三方框架也是在BaseModule中配置。当然,正如我们主Module的配置一样,组件Module也需要配置黄油刀的插件,以及在defaultConfig中加上路由的配置,以及支持Java 8 ,这是必然的,除此之外,他有两个特殊的地方:
可以看到,我们会根据我们定义的变量来加载他到底是App还是Module,这样就能做到我们的随意切换了,如果是App的话,我们还需要给他配置一个包名ID,你可以给他设置相同的包名,我这里做了一些小区分而已。
还有一个地方则是清单文件的配置了 [图片上传失败…(image-6b3943-1607329172143)] sourceSets可以帮助我们替换加载的文件,我们如果是App的话,重新配置了一个清单文件,因为他包含了App所需要的一切,如果是module,则不处理。来看下他们之间的区别:
首先是作为Module的清单文件:
可以看出,他只有必要的四大组件需要配置的时候则配置,不然的话就是空的了
而再看下作为App的清单文件:
他可能比你想象的东西要多,他有一个Application根节点配置App的参数,还需要一个启动项Activity,不然也启动不起来。
6.BaseModule
基类的Module给我们更多的是封装的帮助,我们需要使用到的资源以及第三方框架都是可以放在这里的,老规矩,来看下他的build.gradle
你理解了他,他就变得透明,就是一些常规的添加,并且黄油刀的插件,以及在defaultConfig中加上路由的配置,以及支持Java 8 必不可少。
7.Base类
作为高度统筹的项目架构,在Base方面实际上也是有一定的约束的,这里我以三个类为案例,分别是BaseApp,BaseActivity以及BaseFragment
A.BaseApp
BaseApp方面主要还是做一些初始化的作用,不过你也可以在BaseModule中添加一个统一初始化的方法,BaseApp需要注意的点:
-
1.组件统一Context可以单例Application
-
2.组件Module需要继承自BaseApp
B.BaseActivity
BaseActivity中,我们初始化了黄油刀,以及封装了View,这样的好处就是不用写这么多onCreate了,使用起来也异常的方便
[图片上传失败…(image-66e0c9-1607329172143)]
C.BaseFragment
至于Fragment,和Activity的封装是一样的
唯一要注意的就是黄油刀的使用了,不过这个我们会在黄油刀中所讲到
8.ARouter
路由是帮助我们组件间跳转的,根据Github上添加好依赖之后,我们需要注意一下的几点
-
1.Path至少是两个层级 类似于 /Test/AppMain 程序会先去找Test再去找AppMain
-
2.Path第一层级不能重复,如果又出现一个 /Test/AppTest 则会出现找不到的异常
只要在Activity前一行添加path即可定义目标地址
这里我封装了一个帮助类提供跳转 [图片上传失败…(image-6213ee-1607329172143)]
地址也是自己定义的 [图片上传失败…(image-aff4f2-1607329172143)]
9.Butterknife
黄油刀只是作为高效开发的组件,你也同样可以使用原生的findViewById,那么如果我们使用到黄油刀,需要注意什么呢?
-
1.Activity中绑定ButterKnife.bind(this);
-
2.Fragment以及Adapter中绑定ButterKnife.bind(this,mView);
-
3.Module中引用ID需要使用R2,如图
三.组件化的实现
这里我基于此架构写了一个仿微信UI的Demo内容,让大家更加清晰的认识组件化,那么我们先来看下预览:
首先我们App的空壳就是引用的四个组件,每个组件中都存在一个Fragment,App Module 只是做整合,每个组件Module单独负责一个业务,并且他们都是可以单独作为Apk存在的
[图片上传失败…(image-9b5e6c-1607329172143)]
我们可以全部都单独的实现运行
而在模拟器上的表现如下:
四.组件化的问题
1.资源名冲突
如果资源名冲突,要么他改,要么你改,如果他改不了,那就你改,如果你也改不了,那么我们就通过Gradle去转换了,在Project的build.gradle中添加
2.包名问题
部分第三方SDK需要填写包名,那么这个时候如果你填写主Module的包名的话,申请的Key实际上组件Module是用不了的,这里可以选择组件Module使用同一个包名,或者通过BaseModule的包名去申请,这样在BaseModule中再封装一层,提供给外部访问即可。
3.组件间的通讯
组件间通讯,可以选择EventBus,广播等方式,复杂交互的话,ARouter提供了一个Provider供我们数据交互。
uGuiLinAndroid/AndroidComponent#4%E7%BB%84%E4%BB%B6%E5%8C%96%E4%B8%8Emvp)4.组件化与MVP
看到不少开源使用了组件化还使用了MVP,我自己也尝试写了一个,只能感叹代码量增加很多,敲得手抖疼了,随即开始思考这个架构,组件化应对的是业务解耦,而MVP,更倾向于代码解耦,结合起来肯定代码更加清晰,更加完善,但是我无法提供一个这么庞大的项目练手,所以如果你的项目不是很庞大,可以择优选择,架构再好,也要看适不适合。
五.ARouter拦截
我们在一些特殊的场景的时候,需要拦截跳转,一般的例子比如跳转登录页的时候就可以拦截了,那么ARouter的拦截怎么处理的呢?我们来看下代码
我们只需要配置Interceptor的注解即可,其中优先级和name可以自己定义,而init是初始化的,并且只会走一次,主要还是在process中我们可以根据判断条件来控制是否拦截,这里我写了一些伪代码,如果想获取当前Activity对象的话,可以在Application中监听Activity生命周期获得
六.结尾
组件化好处还是很多的,比如提升编译速度,毕竟都是单Module开发,高度统筹的情况下,还能基于BaseModule来减少重复代码,要是发现哪个Module还单独写工具类,拉出去枪毙。
看那文章毕竟是片面的,我还是由衷的希望读者在看完文章之后下载代码来运行一遍,看看代码的结构,那么理解这个demo也就八九不离十了,再结合自己的理解,就会看到更加广阔的天地了。
源代码地址: AndroidComponent