Android应用开发之Android组件化+Arouter通讯解析
凌雪 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
看完这篇文章有何感觉?已经有0人表态,0%的人喜欢 快给朋友分享吧~
评论(0)
后参与评论

您输入的评论内容中包含违禁敏感词

我知道了

助您圆梦职场 匹配合适岗位
验证码手机号,获得海同独家IT培训资料
选择就业方向:
人工智能物联网
大数据开发/分析
人工智能Python
Java全栈开发
WEB前端+H5

请输入正确的手机号码

请输入正确的验证码

获取验证码

您今天的短信下发次数太多了,明天再试试吧!

提交

我们会在第一时间安排职业规划师联系您!

您也可以联系我们的职业规划师咨询:

小职老师的微信号:z_zhizuobiao
小职老师的微信号:z_zhizuobiao

版权所有 职坐标-一站式AI+学习就业服务平台 沪ICP备13042190号-4
上海海同信息科技有限公司 Copyright ©2015 www.zhizuobiao.com,All Rights Reserved.
 沪公网安备 31011502005948号    

©2015 www.zhizuobiao.com All Rights Reserved