内容简介:最近因为业务需求变更,有考虑采用组件化架构进行开发,这方面我之前没有接触过。关于组件化的文章很多,各方大神更是提出了各种的组件化方案,我也看了很多相关文章。但是学习新东西看的再多,不如动手做一次,先不考虑复杂的东西,先动手做个简单的Demo更有助于理解组件化的思想。组件化相关理论知识这里就不多讲了,想要了解的可以自己去搜或者去看Android组件化方案这篇文章。废话不多说,直接动手开码。先打开然后在项目目录下新建一个config.gradle文件。
最近因为业务需求变更,有考虑采用组件化架构进行开发,这方面我之前没有接触过。关于组件化的文章很多,各方大神更是提出了各种的组件化方案,我也看了很多相关文章。但是学习新东西看的再多,不如动手做一次,先不考虑复杂的东西,先动手做个简单的Demo更有助于理解组件化的思想。组件化相关理论知识这里就不多讲了,想要了解的可以自己去搜或者去看Android组件化方案这篇文章。废话不多说,直接动手开码。
2、搭建组件化Demo
先打开 Android Studio 新建一个项目。
步骤一: 新建config.gradle,统一管理build.gradle中的相关内容
然后在项目目录下新建一个config.gradle文件。
接着在这个文件内添加如下代码:
ext { //applicationId版本号sdkVersion统一管理 android = [ compileSdkVersion : 28, buildToolsVersion : 28, applicationId : "com.example.componenttestdemo", minSdkVersion : 19, targetSdkVersion : 28, versionCode : 1, versionName : "1.0", testInstrumentationRunner: "android.support.test.runner.AndroidJUnitRunner" ] //版本号 def APPCOMPAT_V7_VERSION = "28.0.0" def CONSTRAINT_LAYOUT_VERSION = "1.1.3" //三方库统一管理 dependencies = [ appcompatV7 : 'com.android.support:appcompat-v7:' + APPCOMPAT_V7_VERSION, constraintLayout: 'com.android.support.constraint:constraint-layout:' + CONSTRAINT_LAYOUT_VERSION ] } 复制代码
因为我们知道项目使用组件化架构后,单一模块 Module
可以作为单个 Application
运行,同时也可以在整个主 Application
中作为一个 Module
运行。所以在 config.gradle
中先定义一个 isModule
来区别这两种情况,组件化之后可以通过修改这个值来切换这两种情况的使用。剩下就是对 applicationId
、版本号、 sdkVersion
和三方库等进行统一管理。
接着修改app下的build.gradle里设置内容
将原来的 compileSdkVersion
、 applicationId
、 minSdkVersion
、 versionCode
和三方库等替换成对应config.gradle中定义的值。
apply plugin: 'com.android.application' android { compileSdkVersion rootProject.ext.android.compileSdkVersion defaultConfig { applicationId rootProject.ext.android.applicationId minSdkVersion rootProject.ext.android.minSdkVersion targetSdkVersion rootProject.ext.android.targetSdkVersion versionCode rootProject.ext.android.versionCode versionName rootProject.ext.android.versionName testInstrumentationRunner rootProject.ext.android.testInstrumentationRunner } buildTypes { release { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' } } } dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) implementation rootProject.ext.dependencies.appcompatV7 implementation rootProject.ext.dependencies.constraintLayout } 复制代码
最后还要在项目目录下的build.gradle中添加一行:
apply from : "config.gradle" 复制代码然后点击
Sync Now
同步。最后在进行下一步前,新建一个MyApplication,在
AndroidManifest
设置name属性。
步骤二:创建Main模块,搬空app壳工程
我们知道组件化中需要一个app壳工程,这个壳工程中不处理任何业务,就只是一个空壳,由它将所需要的各个组件模块组合起来,构成一个完整的应用。而现在项目中的app还是存在默认的入口 Activity
的,所以要新建一个 ModuleMain
将默认的 MainActivity
和其布局文件搬过去。
接着进入app的 AndroidManifest
文件将注册Activity的相关代码也搬到 ModuleMain
模块的 AndroidManifest
中去,只留下 application
标签。
这里注意组件化项目中每个Module都会有自己的 AndroidManifest
文件,最后打包时会将这些文件合并成一个文件,所以会出现 application
标签中的属性重复问题,要在app的 AndroidManifest
文件中添加如下两行代码:
xmlns:tools="http://schemas.android.com/tools" 复制代码
tools:replace="android:name,android:label,android:icon, android:theme,android:allowBackup" 复制代码
这里的 name
、 label
、 icon
、 theme
、 allowBackup
都可能会有重复,所以全部写上之间用逗号隔开。完整 AndroidManifest
如下:
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.sy.modulesimpledemo" xmlns:tools="http://schemas.android.com/tools" > <application android:name=".application.MyApplication" android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" tools:replace="android:name,android:label,android:icon, android:theme,android:allowBackup" android:theme="@style/AppTheme"> </application> </manifest> 复制代码
接着app壳工程中只剩刚修改的 build.gradle
还没删减,在删减前先将app中 build.gradle
的内容复制覆盖到Main模块的 build.gradle
中,并且还要做部分修改。因为单个组件可以作为一个组件模块被app壳工程组合使用,也可以单独作为一个 application
使用。所以要根据 config.gradle
中定义的 isModule
来判断是作为Module还是Applicaition。同样还有作为Module是不需要 applicationId
的而作为应用则是需要的。
//通过isModule来判断是application还是module if (rootProject.ext.isModule) { apply plugin: 'com.android.library' } else { apply plugin: 'com.android.application' } android { compileSdkVersion rootProject.ext.android.compileSdkVersion defaultConfig { //是application才需要applicationId if (!rootProject.ext.isModule) { applicationId "com.example.sy.moduledmain" } minSdkVersion rootProject.ext.android.minSdkVersion targetSdkVersion rootProject.ext.android.targetSdkVersion versionCode rootProject.ext.android.versionCode versionName rootProject.ext.android.versionName testInstrumentationRunner rootProject.ext.android.testInstrumentationRunner } buildTypes { release { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' } } } } dependencies { implementation fileTree(include: ['*.jar'], dir: 'libs') implementation rootProject.ext.dependencies.appcompatV7 implementation rootProject.ext.dependencies.constraintLayout } 复制代码
这时modulemain中的 AndroidManifest
会提示资源文件的缺少,这时先将app中的对应文件复制到modulemain里来。
步骤三 :新建 Application
和 AndroidManifest
文件
在app壳工程和ModuleMain中分别新建一个 Application
,因为Moudule也是需要可以单独运行的。
AndroidManifest
文件,因为作为
Module
和
Application
是会有不一样的所以要做区分,在main目录下新建module文件夹和application文件夹分别存放两个情况下的
AndroidManifest
文件,将原来的
AndroidManifest
文件拖到module下,再拷贝一份到application下。拷贝完了记得在两个
AndroidManifest
里
application
标签下设置name属性。
接着再 build.gradle
中添加如下代码,用来分别在两种情况下指定使用哪个 AndroidManifest
。
sourceSets { main { if (rootProject.ext.isModule) { manifest.srcFile 'src/main/module/AndroidManifest.xml' } else { manifest.srcFile 'src/main/application/AndroidManifest.xml' java { //排除java/module文件夹下的所有文件 exclude '*module' } } } } 复制代码
然后再到app的 build.gradle
中在 dependencies
内添加以下代码,用来引入ModuleMain模块。
if (rootProject.ext.isModule) { implementation project(":modulemain") } 复制代码
现在可以再次点击 Sync Now
等同步结束后,虽然项目中只有一个壳工程和一个主Module,但是已可以看到组件化的雏形。此时已经可以通过修改 config.gradle
里的 isModule
的值,进行 Application
和 Module
两种模式的切换,将ModuleMain作为app 的模块运行或者是单独作为一个应用运行了。
步骤四:新建其他组件Module和解决资源文件冲突
接着按照新建ModuleMain的步骤重复新建其他业务Module,这里我新建了3个Module,业务A:ModuleA与业务B:ModuleB和一个BaseModule。其中BaseModule主要存放一些基础类和 工具 类,只做为Module为上层业务模块提供服务。
接下来解决资源文件冲突的问题,进入ModuleMain的build.gradle
添加下面这行代码,为资源文件命名规范一个统一开头:
resourcePrefix "modulemain_" 复制代码
添加后起名是没按照规范 Android Studio
就会有一个提示:
按要求修改文件名后提示消失。
步骤五:使用ARouter进行组件间通信
接下来就要处理组件间的通信问题,采用阿里的 ARouter 。按照文档集成 ARouter 。 首先在 defaultConfig
下添加如下代码:
javaCompileOptions { annotationProcessorOptions { arguments = [AROUTER_MODULE_NAME: project.getName()] } } } 复制代码
再引入 ARouter
依赖:
implementation rootProject.ext.dependencies.arouter implementation rootProject.ext.dependencies.arouterCompiler 复制代码
最后在 Application
中初始化 ARouter
:
if (isDebug()) { // 这两行必须写在init之前,否则这些配置在init过程中将无效 ARouter.openLog(); // 打印日志 ARouter.openDebug(); // 开启调试模式(如果在InstantRun模式下运行,必须开启调试模式!线上版本需要关闭,否则有安全风险) } ARouter.init(mApplication); // 尽可能早,推荐在Application中初始化 复制代码
这样 ARouter
就集成好了,接着在MoudleA和ModuleB中新建两个 Activity
,然后使用 ARouter
进行页面跳转。
ModuleMain中MainActivity.java:
public class MainActivity extends BaseActivity { /** * toA */ private Button mModulemainA; /** * toB */ private Button mModulemainB; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.modulemain_activity_main); initView(); initEvent(); } private void initEvent() { mModulemainA.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { ARouter.getInstance().build(ARouterPath.PATH_MOUDULE_A).navigation(); } }); mModulemainB.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { ARouter.getInstance().build(ARouterPath.PATH_MOUDULE_B).withString("key","传递的数据").navigation(); } }); } private void initView() { mModulemainA = (Button) findViewById(R.id.modulemain_a); mModulemainB = (Button) findViewById(R.id.modulemain_b); } } 复制代码
ModuleA中ModuleAActivity.java:
@Route(path = ARouterPath.PATH_MOUDULE_A) public class ModuleAActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.modulea_activity_module_a); } } 复制代码
ModuleB中ModuleBActivity.java:
@Route(path = ARouterPath.PATH_MOUDULE_B) public class ModuleBActivity extends AppCompatActivity { @Autowired(name = "key") String data; /** * TextView */ private TextView mTextViewB; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.moduleb_activity_module_b); ARouter.getInstance().inject(this); initView(); } private void initView() { mTextViewB = (TextView) findViewById(R.id.textViewB); mTextViewB.setText(data); } } 复制代码
运行效果:
这里看到模块之间界面通信正常,并且单个业务模块也可以单独运行,这样一个最基本的组件化架构Demo差不多就完成了。
3、将Module作为远程maven仓库
在开发中,可能会把一些公用Module传到私有服务器上,然后在项目中直接依赖使用。下面就将Module上传到Github作为远程maven仓库,在项目直接引用。首先新建一个项目,创建一个UtilModule。
将原来项目中的工具类移到UtilModule中,接着在UtilModule的 build.gradle
中添加以下代码:
apply plugin: 'maven' uploadArchives { repositories.mavenDeployer { def mavenDirPath = file('\\Users\\sy\\AndroidProjects\\UtilModule') // 本地存放地址 repository(url:"file://${mavenDirPath.absolutePath}") pom.project { groupId "com.example.utilmodule" // 包名 artifactId "utilmodule" // module的名字 version "1.0.0" // 版本号 } } } 复制代码
然后点击 gradle
中的 uploadArchives
:
进入设置的目录查看,aar已经打包好了。
接着打开Github创建一个新仓库:
按照Github上的命令,将本地打包好的UtilModule上传到Github上:
上传完成后将仓库地址复制下来,将其中的github.com
部分修改为
raw.githubusercontent.com
再在结尾加上
/master
表示是主分支,添加到项目中的
build.gradle
中。
接着在到Module的build.gradle
中添加依赖:
utilmodule : 'com.example.utilmodule:utilmodule:' + UTIL_MODULE_VERSION 复制代码
implementation rootProject.ext.dependencies.utilmodule 复制代码
这里就是之前设置的包名:Module名:版本号。 SyncNow
之后删除原来项目中的工具类,然后在代码里使用远程仓库的工具类测试:
运行打印日志:
D/com.example.modulemain.MainActivity: onCreate:false 复制代码
这说明远程仓库依赖成功已经能正常使用其中的类和方法。
4、总结
这篇文章主要是记录下我初识组件化,搭建组件化Demo的过程,Demo主要对于我对组件化思想的理解和体验还是很有帮助的,Demo中还有很多没考虑到的地方,比如Application的动态配置合并、Fragment、组件化的混淆等等,也是我正在学习的问题。这篇文章主要供和我一样对组件化这块不太了解的新手做参考,希望能对新手有所帮助。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:- 组件化之路—集成组件SDK
- Android快速开发框架,基础库,样式库,组件化,组件集成
- Android组件化方案及组件消息总线modular-event实战
- 组件化实践
- 组件化架构漫谈
- 前端面试之组件化
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
RGB转16进制工具
RGB HEX 互转工具
URL 编码/解码
URL 编码/解码