内容简介:最近因为业务需求变更,有考虑采用组件化架构进行开发,这方面我之前没有接触过。关于组件化的文章很多,各方大神更是提出了各种的组件化方案,我也看了很多相关文章。但是学习新东西看的再多,不如动手做一次,先不考虑复杂的东西,先动手做个简单的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为上层业务模块提供服务。
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
中。
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实战
- 组件化实践
- 组件化架构漫谈
- 前端面试之组件化
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Code Reading
Diomidis Spinellis / Addison-Wesley Professional / 2003-06-06 / USD 64.99
This book is a unique and essential reference that focuses upon the reading and comprehension of existing software code. While code reading is an important task faced by the vast majority of students,......一起来看看 《Code Reading》 这本书的介绍吧!
HTML 编码/解码
HTML 编码/解码
UNIX 时间戳转换
UNIX 时间戳转换