一个自己的网站,厦门企业网站开发公司,手机网站需要什么,手机网站相册代码1.背景介绍在移动端项目功能不断完善和丰富的过程中我们一直在寻找一种可以高效开发且复用率高的开发模式#xff0c;特别是多应用同步开发、管理。在开发过程中你是否遇到需要发布影子工程#xff1f;新建项目是否需要耗费大量时间将原有基类、工具类、第三方通用类库逐个 c… 1.背景介绍 在移动端项目功能不断完善和丰富的过程中我们一直在寻找一种可以高效开发且复用率高的开发模式特别是多应用同步开发、管理。 在开发过程中你是否遇到需要发布影子工程新建项目是否需要耗费大量时间将原有基类、工具类、第三方通用类库逐个 copy 进新项目中在项目不断迭代后是否发现编译时间不断增加 组件化开发可以很好的解决上述问题它实际是将一个完整的项目划分为若干个模块过程类似搭积木一个一个拼接你可以单独使用其中任意一个也可以用多个拼接出各种形状达到高效开发最大复用。 在了解组件化开发之前我们需要先了解组件和模块这两个概念组件:指的是单一的功能组件如地图组件(MapSDK)、支付组件(AnjukePay)、路由组件(Router)等等模块:指的是独立的业务模块如基类模块(common-module)、商城模块(mall-module)、会员模块(member-module)等等模块相对于组件来说粒度更大。2.系统架构图项目由主项目 app商城模块 mall-module会员模块 member-module公共模块 common-module 各个基类(BaseActivity/BaseApplication/BaseAdapter 等)、工具类、网络、图片等一些公共常用的第三方 sdkapp:作为项目的主程序入口生产环境时可以引入其他模块如本项目的的 common-module、mall-modulem、member-module开发调试不涉及到跨模块调用业务时可以单独引入 common-module 依赖运行。mall-module:商城模块编写完整的商城业务逻辑生产环境作为 library 引入 app 主项目开发阶段可以 application 方式单独运行亦可作为商城应用独立发布。member-module:会员模块编写完整的会员业务逻辑生产环境作为 library 引入 app 主项目开发阶段可以 application 方式单独运行亦可作为会员独立发布。common-module:作为整个项目的基石所有基类增加修改均可以在引入项目中生效达到最大复用率提高开发效率。3.实践mall-module、member-module、common-module 作为 library 被引入 app 中运行效果图mall-module 作为应用单独运行效果图主项目 app 创建 项目 build.gradle 配置文件apply plugin: com.alibaba.arouterbuildscript { repositories { google() jcenter() } dependencies { classpath com.android.tools.build:gradle:2.3.3 classpath com.alibaba:arouter-register:1.0.2 }}allprojects { repositories { google() jcenter { url http://jcenter.bintray.com/ } }}task clean(type: Delete) { delete rootProject.buildDir}项目 gradle.properties 全局配置文件#IS_MAIN_APP true主项目为应用 mall-module为library false mall-module为应用可单独启动IS_MAIN_APPtrue#AS 编译配置COMPILE_SDK_VERSION28BUILDTOOLS_VERSION28.0.3MIN_SDK_VERSION15TARGET_SDK_VERSION25#版本号APP_VERSION1APP_VERSION_CODE1.0.1app build.gradle 配置文件apply plugin 根据 ISMAINAPP 值设置为 application 或 libraryif (IS_MAIN_APP.toBoolean()) { apply plugin: com.android.application} else { apply plugin: com.android.library}android { compileSdkVersion Integer.parseInt(COMPILE_SDK_VERSION) buildToolsVersion BUILDTOOLS_VERSION defaultConfig { if (IS_MAIN_APP.toBoolean()) { applicationId com.fenlibao.arouter } minSdkVersion Integer.parseInt(MIN_SDK_VERSION) targetSdkVersion Integer.parseInt(TARGET_SDK_VERSION) versionCode Integer.parseInt(APP_VERSION) versionName APP_VERSION_CODE testInstrumentationRunner android.support.test.runner.AndroidJUnitRunner javaCompileOptions { annotationProcessorOptions { arguments [AROUTER_MODULE_NAME: project.getName(), AROUTER_GENERATE_DOC: enable] } } } buildTypes { release { minifyEnabled false proguardFiles getDefaultProguardFile(proguard-android.txt), proguard-rules.pro } } sourceSets { main { if (IS_MAIN_APP.toBoolean()) { manifest.srcFile src/main/release/AndroidManifest.xml } else { manifest.srcFile src/main/debug/AndroidManifest.xml } } }}dependencies { compile fileTree(dir: libs, include: [*.jar]) annotationProcessor com.alibaba:arouter-compiler:1.2.2 compile project(:common-module)//公共方法 基类 放在该项目中 if (IS_MAIN_APP.toBoolean()) { compile project(:mall-module)//商城模块 compile project(:member-module)//会员模块 }}创建 mall-module mall-module build.gradle 配置文件 apply plugin 根据 ISMALLAPP 值设置为 application 或 libraryif (IS_MALL_APP.toBoolean()) { apply plugin: com.android.application} else { apply plugin: com.android.library}android { compileSdkVersion Integer.parseInt(COMPILE_SDK_VERSION) buildToolsVersion BUILDTOOLS_VERSION defaultConfig { if (IS_MALL_APP.toBoolean()) { applicationId com.fenlibao.mall } minSdkVersion Integer.parseInt(MIN_SDK_VERSION) targetSdkVersion Integer.parseInt(TARGET_SDK_VERSION) versionCode Integer.parseInt(APP_VERSION) versionName APP_VERSION_CODE testInstrumentationRunner android.support.test.runner.AndroidJUnitRunner resourcePrefix mall_ javaCompileOptions { annotationProcessorOptions { arguments [AROUTER_MODULE_NAME: project.getName()] } } } buildTypes { release { minifyEnabled false proguardFiles getDefaultProguardFile(proguard-android.txt), proguard-rules.pro } } sourceSets { main { if (IS_MALL_APP.toBoolean()) { manifest.srcFile src/main/release/AndroidManifest.xml } else { manifest.srcFile src/main/debug/AndroidManifest.xml } } }}dependencies { compile project(:common-module) compile com.android.support.constraint:constraint-layout:1.1.3 annotationProcessor com.alibaba:arouter-compiler:1.2.2}common-module 创建 common-module build.gradle 配置文件 apply plugin 固定为com.android.library作为库被其他项目引用apply plugin: com.android.libraryandroid { compileSdkVersion Integer.parseInt(COMPILE_SDK_VERSION) buildToolsVersion BUILDTOOLS_VERSION defaultConfig { minSdkVersion Integer.parseInt(MIN_SDK_VERSION) targetSdkVersion Integer.parseInt(TARGET_SDK_VERSION) versionCode Integer.parseInt(APP_VERSION) versionName APP_VERSION_CODE testInstrumentationRunner android.support.test.runner.AndroidJUnitRunner javaCompileOptions { annotationProcessorOptions { arguments [ AROUTER_MODULE_NAME : project.getName() ] } } } buildTypes { release { minifyEnabled false proguardFiles getDefaultProguardFile(proguard-android.txt), proguard-rules.pro } }}dependencies { compile fileTree(dir: libs, include: [*.jar]) compile com.android.support:appcompat-v7:28.0.0 compile com.android.support:design:28.0.0 compile com.android.support.constraint:constraint-layout:1.1.3 testCompile junit:junit:4.12 androidTestCompile com.android.support.test:runner:1.0.2 androidTestCompile(com.android.support.test.espresso:espresso-core:3.0.2, { exclude group: com.android.support, module: support-annotations }) compile com.nostra13.universalimageloader:universal-image-loader:1.9.5//该项目中suppourt包为25.2.0版本比较低 顾做排除处理 compile(com.alibaba:arouter-api:1.4.1) { exclude group: com.android.support } //Rxjava2 compile io.reactivex.rxjava2:rxjava:2.2.6 compile io.reactivex.rxjava2:rxandroid:2.1.0 //Retrofit2 compile com.squareup.retrofit2:retrofit:2.4.0 compile com.squareup.retrofit2:converter-gson:2.4.0 compile com.jakewharton.retrofit:retrofit2-rxjava2-adapter:1.0.0 //Okhttp-interceptor compile com.squareup.okhttp3:logging-interceptor:3.6.0}4.注意事项多个 module 间 Activity 如何跳转由于模块与模块之间是相互独立存在因而不能使用项目内方式实现 Activity 跳转下面介绍两种 Activity 跳转方式日常开发中推荐使用方式二方式二不管如何修改类名包名都能保持与字符串常量映射关系维护和使用更方便更多 ARouter 高级用法请查阅相关资料。通过反射方式try { Class clazz Class.forName(com.fenlibao.member.MainActivity); Intent intent new Intent(_activity, clazz); startActivity(intent);} catch (ClassNotFoundException e) { e.printStackTrace();}使用 ARouter 注解方式实现映射关系自动注册/** * ARouter在MyApplication中初始化 */public class MyApplication extends BaseApplication { Override public void onCreate() { super.onCreate(); init(); } private void init() { if (isDebug()) { ARouter.openLog(); ARouter.openDebug(); } ARouter.init(this); } public boolean isDebug() { return getApplicationInfo() ! null (getApplicationInfo().flags ApplicationInfo.FLAG_DEBUGGABLE) ! 0; } Override public void onTerminate() { super.onTerminate(); ARouter.getInstance().destroy(); }}/** * 在常量类中定义静态字符串常量 */public static final String MEMBER_1_URL_MAIN /member/MainActivity;/** * 在对应module Activity中使用Route标签进行绑定 */Route(path RoutePath.MALL_1_URL_MAIN)public class MainActivity extends BaseActivity {}/** * 在需要跳转至该页面build方法中传入对应Activity字符串常量即可实现跳转 */ARouter.getInstance().build(RoutePath.MEMBER_1_URL_MAIN).navigation();在 module 中如何获取 Application 上下文对象在 common-module 中定义 BaseApplication 继承 Application。** * 项目Application基类主项Application需集成此类 */public class BaseApplication extends Application { /** * 系统上下文 */ private static BaseApplication mAppContext; Override public void onCreate() { super.onCreate(); mAppContext this; } /** * 获取系统上下文单例 */ public static BaseApplication getInstance() { return mAppContext; }}在 app 项目中 MyApplication(上部分代码示例中可以查看)继承 BaseApplication同时设置到 AndroidManifest.xml application 标签下 name 属性中。在 app 及 module 中都可通过 BaseApplication.getInstance();方法即可获取应用上下文对象如下:BaseApplication application BaseApplication.getInstance();如何将 module 作为应用单独运行在项目 gradle.properties 全局配置文件中找到 ISMAINAPP 配置变量设置为 ture 时为主项目启动方式设置为 false脱离其他 mall-module 作为应用单独启动设置完成之后重新编译项目即可开发测试阶段推荐使用该方式可缩短项目编译时间项目越大缩短时间越明显。##IS_MAIN_APP true主项目为应用,mall-module为library;false mall-module为应用可单独启动IS_MAIN_APPtrue应用主入口只能有一个如何切换应用主入口根据 ISMAINAPP 设置值加载不同目录下的 AndroidManifest.xml 文件实现根据参数加载配置文件下面是 app mall-module 的 build.gradle 配置。#app build.gradleandroid { sourceSets { main { if (IS_MAIN_APP.toBoolean()) { manifest.srcFile src/main/release/AndroidManifest.xml } else { manifest.srcFile src/main/debug/AndroidManifest.xml } } }}#mall-module build.gradleandroid { sourceSets { main { if (!IS_MAIN_APP.toBoolean()) { manifest.srcFile src/main/release/AndroidManifest.xml } else { manifest.srcFile src/main/debug/AndroidManifest.xml } } }}如何避免资源文件冲突覆盖在组件化开发过程中经常会出现资源文件冲突覆盖问题主项目会覆盖 module 项目资源文件。在 module 项目中 build.gradle 配置文件中设置resourcePrefix mall_通过给模块设置不同的前缀避免资源文件重名覆盖问题。良好的命名(资源文件/类文件)习惯需以 module 前缀开头例如 mall-module 布局资源文件采用 mallactivity_home方式避免资源文件重名覆盖问题如果资源文件不按 resourcePrefix mall 定义前缀命名会有错误提示例如以如下方式命名布局资源文件 activitymallhome.xml组件化开发如何利用 Git 管理代码实现协同开发项目中引用的 module 可能是其他组员负责开发我们只负责调用传递数据当 module 发生改变时项目中需要可以获取到最新的代码本项目中采用 git submodule 方式管理代码如下图1. 增加 git module 项目引用 采用 git submodule add [url][module-name] 命令增加 git 项目引用 urlgit 项目完整路径 module-name为本地项目 module 名称2. 导入完整 git submodule 项目 第一步初始化git submodule init第二步更新项目git submodule update 引用至本地如果遇到提示项目目录已存在将原有项目目录删除再执行更新命令即可。5.总结 以上就是组件化开发的详细步骤和相关注意事项如果你面前是一个庞大的工程建议你使用该方案以最小的代价尽快开始实施组件化。如果你现在负责的是一个开发初期的项目代码量还不大那么也建议尽快进行组件化的规划不要给未来的自己增加徒劳的工作量。 项目示例 Github 地址:https://github.com/guixia/Android-Submodule.git。- END -更多推荐内容《kubernetes 单master集群的搭建》