Android组件化+Arouter通讯解析
android化+arouter通讯解析。
实际开发中越是大型的项目,代码量越多,而androidstudio编译的速度越慢。除了抬高电脑配置外,如何提高程序员的开发效率越是迫在眉睫。除此之外,团队合作开发,合并代码也是一个头疼的问题。虽然可以使用svn/git来规避一些问题,但团队中一个人的代码出了问题,导致自己也是*停止开发也是可能的。
组件化:
项目代码臃肿的时候,通常考虑拆分代码,分层的方式。组件化是将项目按照业务拆分成一个个组件,进而达到解耦分层。一个组件化必须能够单独调试,集成编译,数据传输,ui转跳,生命周期,代码边界这六大特征。
通过一个组件化模型来进一步了解:
通过上图可知:
空壳app : 负责管理各个业务组件,和打包apk,没有具体的业务功能; main组件 :属于业务组件,指定app启动页面、主界面 movie组件 :属于业务组件,用于显示电影列表 collection组件 : 属于业务组件,用于显示收藏的电影列表 commonlibrary(基类库) : 属于功能组件,提供业务组件需要的通用的功能,例如:网络请求,图片加载,mvp框架,工具类,每个组件的数据实体等等。1.先配置依赖库和版本号统一的管理。
工欲善其事必先利其器,不能因配置问题导致开发拖延,因此先配置好需要的各种库。
本项目使用到以下库
android 官方的常见库 rxjava和rxandroid 异步操作库 retrofit,okhtttp 网络库 glide 图片加载库 sqlbrite轻量级数据操作库 arouter路由通讯库先创建一个config.gradle,编写以下代码:
// 第三方库,app的版本号的管理和组件模式的切换配置 ext{ isalone=false; //false:作为lib集成存在, true:作为application组件存在 android = [ compilesdkversion : 27, minsdkversion :15, targetsdkversion :27, versioncode :1, versionname :"1.0", ] libsversion=[ // app dependencies version supportlibraryversion = "27.0.2", support_v4 = "27.0.2", arouter_api = "1.3.1", arouter_compiler = "1.1.4", sqlbrite="1.1.1", rxjava="1.3.0", rxandroid="1.2.1", retrofit="2.3.0", converter_gson="2.3.0", adapter_rxjava="2.3.0", okhttp="3.8.0", logging_interceptor="3.8.0", glide="3.8.0", ] dependencies = [ //android 官方库 appcompatv7 : "com.android.support:appcompat-v7:$rootproject.supportlibraryversion", support_v4 : "com.android.support:support-v4:$rootproject.support_v4", design : "com.android.support:design:$rootproject.supportlibraryversion", cardview : "com.android.support:cardview-v7:$rootproject.supportlibraryversion", palette : "com.android.support:palette-v7:$rootproject.supportlibraryversion", recycleview : "com.android.support:recyclerview-v7:$rootproject.supportlibraryversion", annotations : "com.android.support:support-annotations:$rootproject.supportlibraryversion", //路由通讯 arouter_api : "com.alibaba:arouter-api:$rootproject.arouter_api", arouter_compiler : "com.alibaba:arouter-compiler:$rootproject.arouter_compiler", // sqlbrite sqlbrite :"com.squareup.sqlbrite:sqlbrite:$rootproject.sqlbrite", //rxjava rxjava :"io.reactivex:rxjava:$rootproject.rxjava", rxandroid :"io.reactivex:rxandroid:$rootproject.rxandroid", // okhttp okhttp :"com.squareup.okhttp3:okhttp:$rootproject.okhttp", logging_interceptor :"com.squareup.okhttp3:logging-interceptor:$rootproject.logging_interceptor", //retrofit retrofit :"com.squareup.retrofit2:retrofit:$rootproject.retrofit", converter_gson :"com.squareup.retrofit2:converter-gson:$rootproject.converter_gson", adapter_rxjava :"com.squareup.retrofit2:adapter-rxjava:$rootproject.adapter_rxjava", //glide glide :"com.github.bumptech.glide:glide:$rootproject.glide", ] }
接下来,在project的build.gradle中添加以下代码,进行配置引用。
apply from:"config.gradle"
在每一个module组件中,进行依赖。
先在commonlibrary基类库中builde.gradle进行依赖:
apply plugin: 'com.android.library' android { compilesdkversion rootproject.ext.android.compilesdkversion defaultconfig { minsdkversion rootproject.ext.android.minsdkversion targetsdkversion rootproject.ext.android.targetsdkversion versioncode rootproject.ext.android.versioncode versionname rootproject.ext.android.versionname javacompileoptions { annotationprocessoroptions { arguments = [modulename: project.getname()] } } } } dependencies { implementation filetree(include: ['*.jar'], dir: 'libs') //android support ,任何一个module依赖的官方包都在这里配置 api(rootproject.ext.dependencies.appcompatv7) { exclude module: "support-annotations" exclude module: "support-v4" } api(rootproject.ext.dependencies.support_v4) { exclude module: "support-annotations" } api rootproject.ext.dependencies.recycleview api rootproject.ext.dependencies.design api rootproject.ext.dependencies.annotations // arouter 依赖 api rootproject.ext.dependencies.arouter_api //rxjava api(rootproject.ext.dependencies.rxjava) { exclude module: "rxandroid" } api rootproject.ext.dependencies.rxandroid //sqlbrite api rootproject.ext.dependencies.sqlbrite //retrofit api rootproject.ext.dependencies.retrofit api rootproject.ext.dependencies.converter_gson api rootproject.ext.dependencies.adapter_rxjava // okhttp api rootproject.ext.dependencies.okhttp api rootproject.ext.dependencies.logging_interceptor //glide api rootproject.ext.dependencies.glide }
最后,每一个业务组件(例如:movie组件和collection组件)的build.gradle依赖:
android { compilesdkversion rootproject.ext.android.compilesdkversion defaultconfig { minsdkversion rootproject.ext.android.minsdkversion targetsdkversion rootproject.ext.android.targetsdkversion versioncode rootproject.ext.android.versioncode versionname rootproject.ext.android.versionname testinstrumentationrunner "android.support.test.runner.androidjunitrunner" if (rootproject.ext.isalone) { // 组件模式下设置applicationid applicationid "com.xingen.collection" } javacompileoptions { annotationprocessoroptions { arguments = [modulename: project.getname()] } } } } dependencies { implementation project(':commonlibrary') //集成模式下需要编译器生成路由通信的代码 annotationprocessor rootproject.ext.dependencies.arouter_compiler }
整个项目的结构,如下所示:
2. 编写commonlibrary基类库
将每个业务组件需要用到的通用操作都封装到一个通用的commonlibrary基类库中,然后直接在每个业务组件中依赖该库。
如下图所示,将一些常见的操作,实体类,网络操作,图片加载,mvp架构等等。 除此之外,统一的style风格,权限也应该定义在commonlibrary中。
除此之外,每个组件的application问题。如何获取每个组件的通用application?
写一个超类baseapplication,将一些常见初始化操作放到里面.
public class baseapplication extends application { private static baseapplication instance; @override public void oncreate() { super.oncreate(); instance=this; initrouter(); } public static baseapplication getinstance(){ return instance; } private void initrouter(){ if (buildconfig.debug) { //一定要在arouter.init之前调用opendebug arouter.opendebug(); arouter.openlog(); } arouter.init(this); } }
写一个工具类,让每个组件可以获取到这个baseapplication。
public class contextutils { public static baseapplication getappcontext(){ return baseapplication.getinstance(); } }
然后让每个组件的application去继承这个baseapplication。以movie组件为例。
public class movielistapplication extends baseapplication{ @override public void oncreate() { super.oncreate(); } }
最后在组件的androidmanifest.xml中去引用该定义的movielistapplication。
3. 集成和组件模式的切换
组件化具备每个组件单独调试和集成的特点。
在config.gradle中设置一个标志,便于切换。
ext{ isalone=false; //false:作为lib集成存在, true:作为application组件存在 }
组件的组件模式是指单独调试的application项目,集成模式是指library项目,依赖到空壳app中。
这里以movie组件为案例,来介绍,在其build.gradle中。
//控制组件模式和集成模式 if (rootproject.ext.isalone) { apply plugin: 'com.android.application' } else { apply plugin: 'com.android.library' } android { defaultconfig { if (rootproject.ext.isalone) { // 组件模式下设置applicationid applicationid "com.xingen.movie" } } }
每次切换模式,androidstudio需要sync 下,在运行对应的项目。
4. 一些常见问题处理
4.1 组件在集成模式和组件模式下的代码和androidmanifest.xml
在组件模式下,需要单独调试,具备mainactivity和applciation类。
这里以movie组件为例,在java文件夹下创建一个debug文件夹,放入对应mainactivity和applciation类。
在main文件夹下创建一个module文件夹,放入组件模式下的androidmanifest.xml。
而集成模式下的androidmanifext.xml,不能有application和主的activity,不能声明app名称、图标等属性。
最后在gradle配置,*切换集成模式和组件模式下的不同代码。
android { sourcesets { main { //控制两种模式下的资源和代码配置情况 if (rootproject.ext.isalone) { manifest.srcfile 'src/main/module/androidmanifest.xml' } else { manifest.srcfile 'src/main/androidmanifest.xml' //集成开发模式下排除debug文件夹中的所有java文件 java { exclude 'debug/**' } } } } }
最终,movie组件项目的结构,如下所示:
4.2 资源命名冲突
若是多个组件项目中都具备相同名字的图标,那么集成打包app会报错。
最好的解决方式:就是每个组件的资源文件(图片,xml)都约定好以什么组件名为前缀。
4.3 library依赖问题
第三方依赖库可能到引入重复包问题,通过exclude module去除指定重复包,具体详情查看1.先配置依赖库和版本号统一的管理。
5. 阿里arouter通讯
模块之间的通讯通过arouter来实现。
例如,main模块中要获取到movie模块中的一个fragment类,但两个模块又不能直接依赖。通过arouter的暴露服务来通讯可以解决。
先在commonlibraray中定义一个iprovider子类,定义一个服务.
public interface movielistprovider extends iprovider { fragment createfragment(); }
定义该服务的路径:
public final class routerpath { /** * 电影列表的路径 */ public static final string path_movie_list="/movieservice/movie_list"; }
然后在movie组件中,实现该服务。
@route(path = routerpath.path_movie_list) public class movielistproviderimpl implements movielistprovider { @override public fragment createfragment() { movielistfragment fragment=movielistfragment.newinstance(); movielistpresenter presenter=new movielistpresenter(fragment, netclient.getinstance(), sqlclient.getinstance()); return fragment; } @override public void init(context context) { } }
最后在main组件中获取该服务对象,从而获取到movie组件中的fragment。
public class mainactivity extends baseactivity implements navigationview.onnavigationitemselectedlistener { @autowired movielistprovider movielistprovider; @override public void init(bundle savedinstancestate) arouter.getinstance().inject(this); fragment fragment = movielistprovider.createfragment(); getsupportfragmentmanager().begintransaction().add(r.id.movielist_content_layout, fragment).commit(); } }
当然,还有很多关于arouter的用法,请点击查看arouter文档。
6. 运行效果:
单独movie组件效果:
上一篇: 知名软件站点遭Google浏览器拦截报毒
下一篇: python字符串处理以及字符串格式化