凌雪
2018-10-24
来源 :网络
阅读 1349
评论 0
摘要:本文将带你了解Android应用开发之Android组件化+Arouter通讯解析,希望本文对大家学Android有所帮助。
本文将带你了解Android应用开发之Android组件化+Arouter通讯解析,希望本文对大家学Android有所帮助。
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中添加以下代码,进行配置引用。
?1apply 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文档。
本文由职坐标整理并发布,希望对同学们有所帮助。了解更多详情请关注职坐标移动开发之Android频道!
喜欢 | 0
不喜欢 | 0
您输入的评论内容中包含违禁敏感词
我知道了

请输入正确的手机号码
请输入正确的验证码
您今天的短信下发次数太多了,明天再试试吧!
我们会在第一时间安排职业规划师联系您!
您也可以联系我们的职业规划师咨询:
版权所有 职坐标-一站式AI+学习就业服务平台 沪ICP备13042190号-4
上海海同信息科技有限公司 Copyright ©2015 www.zhizuobiao.com,All Rights Reserved.
沪公网安备 31011502005948号