android sdk方法隐藏_每个Android开发都必须知道的利器
1.背景介紹
??在移動端項目功能不斷完善和豐富的過程中我們一直在尋找一種可以高效開發(fā)且復(fù)用率高的開發(fā)模式,特別是多應(yīng)用同步開發(fā)、管理。
??在開發(fā)過程中你是否遇到需要發(fā)布影子工程?新建項目是否需要耗費大量時間將原有基類、工具類、第三方通用類庫逐個 copy 進新項目中?在項目不斷迭代后是否發(fā)現(xiàn)編譯時間不斷增加?
??組件化開發(fā)可以很好的解決上述問題,它實際是將一個完整的項目劃分為若干個模塊,過程類似搭積木,一個一個拼接,你可以單獨使用其中任意一個,也可以用多個拼接出各種形狀,達到高效開發(fā),最大復(fù)用。
?在了解組件化開發(fā)之前我們需要先了解組件和模塊這兩個概念
組件:指的是單一的功能組件,如地圖組件(MapSDK)、支付組件(AnjukePay)、路由組件(Router)等等;
模塊:指的是獨立的業(yè)務(wù)模塊,如基類模塊(common-module)、商城模塊(mall-module)、會員模塊(member-module)等等;模塊相對于組件來說粒度更大。
2.系統(tǒng)架構(gòu)圖
項目由主項目 app,商城模塊 mall-module,會員模塊 member-module,公共模塊 common-module 各個基類(BaseActivity/BaseApplication/BaseAdapter 等)、工具類、網(wǎng)絡(luò)、圖片等一些公共常用的第三方 sdk:
app:作為項目的主程序入口,生產(chǎn)環(huán)境時可以引入其他模塊如本項目的的 common-module、mall-modulem、member-module;開發(fā)調(diào)試不涉及到跨模塊調(diào)用業(yè)務(wù)時可以單獨引入 common-module 依賴運行。
mall-module:商城模塊,編寫完整的商城業(yè)務(wù)邏輯,生產(chǎn)環(huán)境作為 library 引入 app 主項目,開發(fā)階段可以 application 方式單獨運行,亦可作為商城應(yīng)用獨立發(fā)布。
member-module:會員模塊,編寫完整的會員業(yè)務(wù)邏輯,生產(chǎn)環(huán)境作為 library 引入 app 主項目,開發(fā)階段可以 application 方式單獨運行,亦可作為會員獨立發(fā)布。
common-module:作為整個項目的基石,所有基類增加修改,均可以在引入項目中生效,達到最大復(fù)用率,提高開發(fā)效率。
3.實踐
mall-module、member-module、common-module 作為 library 被引入 app 中運行效果圖:
mall-module 作為應(yīng)用單獨運行效果圖:
主項目 app 創(chuàng)建 項目 build.gradle 配置文件:
apply plugin: 'com.alibaba.arouter'
buildscript {
? ?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主項目為應(yīng)用 mall-module為library false mall-module為應(yīng)用可單獨啟動
IS_MAIN_APP=true
#AS 編譯配置
COMPILE_SDK_VERSION=28
BUILDTOOLS_VERSION=28.0.3
MIN_SDK_VERSION=15
TARGET_SDK_VERSION=25
#版本號
APP_VERSION=1
APP_VERSION_CODE=1.0.1
app build.gradle 配置文件:apply plugin 根據(jù) ISMAINAPP 值設(shè)置為 application 或 library
if (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')//會員模塊
? ?}
}
創(chuàng)建 mall-module: mall-module build.gradle 配置文件 apply plugin 根據(jù) ISMALLAPP 值設(shè)置為 application 或 library
if (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 創(chuàng)建: common-module build.gradle 配置文件 apply plugin 固定為'com.android.library'作為庫被其他項目引用
apply plugin: 'com.android.library'
android {
? ?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 如何跳轉(zhuǎn)?
由于模塊與模塊之間是相互獨立存在,因而不能使用項目內(nèi)方式實現(xiàn) Activity 跳轉(zhuǎn),下面介紹兩種 Activity 跳轉(zhuǎn)方式,日常開發(fā)中推薦使用方式二,方式二不管如何修改類名包名都能保持與字符串常量映射關(guān)系,維護和使用更方便,更多 ARouter 高級用法請查閱相關(guān)資料。
通過反射方式:
try {
? ?Class clazz = Class.forName("com.fenlibao.member.MainActivity");
? ?Intent intent = new Intent(_activity, clazz);
? ?startActivity(intent);
} catch (ClassNotFoundException e) {
? ?e.printStackTrace();
}
使用 ARouter 注解方式,實現(xiàn)映射關(guān)系自動注冊:
/**
* 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();
? ?}
}
/**
* 在常量類中定義靜態(tài)字符串常量
*/
public static final String MEMBER_1_URL_MAIN = "/member/MainActivity";
/**
* 在對應(yīng)module Activity中使用@Route標簽進行綁定
*/
@Route(path = RoutePath.MALL_1_URL_MAIN)
public class MainActivity extends BaseActivity {
}
/**
* 在需要跳轉(zhuǎn)至該頁面build方法中傳入對應(yīng)Activity字符串常量,即可實現(xiàn)跳轉(zhuǎn)
*/
ARouter.getInstance().build(RoutePath.MEMBER_1_URL_MAIN).navigation();
在 module 中如何獲取 Application 上下文對象?
在 common-module 中定義 BaseApplication 繼承 Application。
**
* 項目Application基類主項Application需集成此類
*/
public class BaseApplication extends Application {
? ?/**
? ? * 系統(tǒng)上下文
? ? */
? ?private static BaseApplication mAppContext;
? ?@Override
? ?public void onCreate() {
? ? ? ?super.onCreate();
? ? ? ?mAppContext = this;
? ?}
? ?/**
? ? * 獲取系統(tǒng)上下文單例
? ? */
? ?public static BaseApplication getInstance() {
? ? ? ?return mAppContext;
? ?}
}
在 app 項目中 MyApplication(上部分代碼示例中可以查看)繼承 BaseApplication,同時設(shè)置到 AndroidManifest.xml application 標簽下 name 屬性中。
在 app 及 module 中都可通過 BaseApplication.getInstance();方法即可獲取應(yīng)用上下文對象,如下:
BaseApplication application = BaseApplication.getInstance();
如何將 module 作為應(yīng)用單獨運行?
在項目 gradle.properties 全局配置文件中找到 ISMAINAPP 配置變量,設(shè)置為 ture 時為主項目啟動方式,設(shè)置為 false,脫離其他 mall-module 作為應(yīng)用單獨啟動,設(shè)置完成之后重新編譯項目即可,開發(fā)測試階段推薦使用該方式,可縮短項目編譯時間,項目越大,縮短時間越明顯。
##IS_MAIN_APP true主項目為應(yīng)用,mall-module為library;false mall-module為應(yīng)用可單獨啟動
IS_MAIN_APP=true
應(yīng)用主入口只能有一個,如何切換應(yīng)用主入口?
根據(jù) ISMAINAPP 設(shè)置值加載不同目錄下的 AndroidManifest.xml 文件,實現(xiàn)根據(jù)參數(shù)加載配置文件,下面是 app mall-module 的 build.gradle 配置。
#app build.gradle
android {
? ?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.gradle
android {
? ?sourceSets {
? ? ? ? ? ?main {
? ? ? ? ? ? ? ?if (!IS_MAIN_APP.toBoolean()) {
? ? ? ? ? ? ? ? ? ?manifest.srcFile 'src/main/release/AndroidManifest.xml'
? ? ? ? ? ? ? ?} else {
? ? ? ? ? ? ? ? ? ?manifest.srcFile 'src/main/debug/AndroidManifest.xml'
? ? ? ? ? ? ? ?}
? ? ? ? ? ?}
? ? ? ?}
}
如何避免資源文件沖突覆蓋?
在組件化開發(fā)過程中經(jīng)常會出現(xiàn)資源文件沖突覆蓋問題,主項目會覆蓋 module 項目資源文件。
在 module 項目中 build.gradle 配置文件中設(shè)置:
resourcePrefix "mall_"
通過給模塊設(shè)置不同的前綴,避免資源文件重名覆蓋問題。
良好的命名(資源文件/類文件)習慣,需以 module 前綴開頭,例如 mall-module 布局資源文件,采用 mallactivity_home,方式避免資源文件重名覆蓋問題,如果資源文件不按 resourcePrefix "mall" 定義前綴命名會有錯誤提示,例如以如下方式命名布局資源文件 activitymallhome.xml:
組件化開發(fā)如何利用 Git 管理代碼,實現(xiàn)協(xié)同開發(fā)?
項目中引用的 module 可能是其他組員負責開發(fā),我們只負責調(diào)用傳遞數(shù)據(jù),當 module 發(fā)生改變時,項目中需要可以獲取到最新的代碼,本項目中采用 git submodule 方式管理代碼,如下圖:
1. 增加 git module 項目引用?采用 git submodule add [url][module-name] 命令增加 git 項目引用 url:git 項目完整路徑; module-name:為本地項目 module 名稱
2. 導入完整 git submodule 項目?第一步初始化:git submodule init;第二步更新項目:git submodule update 引用至本地,如果遇到提示項目目錄已存在,將原有項目目錄刪除再執(zhí)行更新命令即可。
5.總結(jié)
??以上就是組件化開發(fā)的詳細步驟和相關(guān)注意事項,如果你面前是一個龐大的工程,建議你使用該方案,以最小的代價盡快開始實施組件化。如果你現(xiàn)在負責的是一個開發(fā)初期的項目,代碼量還不大,那么也建議盡快進行組件化的規(guī)劃,不要給未來的自己增加徒勞的工作量。 項目示例 Github 地址:https://github.com/guixia/Android-Submodule.git。
- END -
更多推薦內(nèi)容
《kubernetes 單master集群的搭建》
總結(jié)
以上是生活随笔為你收集整理的android sdk方法隐藏_每个Android开发都必须知道的利器的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 互联网三大基石
- 下一篇: php time java_java 时