refactor: 重构

This commit is contained in:
Quyunshuo
2021-04-24 18:12:23 +08:00
parent d75956a81d
commit 42c89b7872
85 changed files with 1031 additions and 639 deletions

View File

@ -1,85 +0,0 @@
import com.quyunshuo.androidbaseframemvvm.build.*
plugins {
id 'com.android.library'
id 'kotlin-android'
id 'kotlin-kapt'
}
android {
compileSdkVersion ProjectBuildConfig.compileSdkVersion
buildToolsVersion ProjectBuildConfig.buildToolsVersion
defaultConfig {
minSdkVersion ProjectBuildConfig.minSdkVersion
targetSdkVersion ProjectBuildConfig.targetSdkVersion
versionCode ProjectBuildConfig.versionCode
versionName ProjectBuildConfig.versionName
testInstrumentationRunner AndroidX.AndroidJUnitRunner
consumerProguardFiles "consumer-rules.pro"
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
kotlinOptions {
jvmTarget = JavaVersion.VERSION_1_8.toString()
}
buildFeatures {
viewBinding = true
}
resourcePrefix "base_"
}
kapt {
arguments {
arg("AROUTER_MODULE_NAME", project.getName())
}
}
dependencies {
implementation fileTree(dir: "libs", include: ["*.jar"])
api AndroidX.CoreKtx
api AndroidX.AppCompat
api AndroidX.ConstraintLayout
api AndroidX.ActivityKtx
api AndroidX.FragmentKtx
api AndroidX.MultiDex
api Kotlin.Kotlin
api Kotlin.CoroutinesCore
api Kotlin.CoroutinesAndroid
api JetPack.LifecycleRuntimeKtx
api JetPack.LifecycleViewModel
api JetPack.LifecycleViewModelKtx
api GitHub.OkHttp
api GitHub.OkHttpInterceptorLogging
api GitHub.Retrofit
api GitHub.RetrofitConverterGson
api GitHub.Gson
api GitHub.MMKV
api GitHub.AutoSize
api GitHub.Glide
api GitHub.ARoute
api GitHub.RecyclerViewAdapter
api GitHub.StatusBar
api GitHub.EventBus
api GitHub.Bugly
api GitHub.BuglyNative
api GitHub.PermissionX
kapt GitHub.GlideCompiler
kapt GitHub.ARouteCompiler
kapt GitHub.EventBusAPT
debugApi GitHub.Chuck
debugApi GitHub.LeakCanary
releaseApi GitHub.ChuckNo
}

View File

@ -1 +0,0 @@
<manifest package="com.quyunshuo.base" />

View File

@ -1,30 +0,0 @@
package com.quyunshuo.base.handler
import android.os.Handler
import android.os.Looper
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.LifecycleObserver
import androidx.lifecycle.LifecycleOwner
import androidx.lifecycle.OnLifecycleEvent
/**
* @Author: QuYunShuo
* @Time: 2020/9/17
* @Class: LifecycleHandler
* @Remark: 自动在UI销毁时移除msg和任务的Handler不会有内存泄露
*/
class LifecycleHandler(
private val lifecycleOwner: LifecycleOwner,
looper: Looper = Looper.getMainLooper()
) : Handler(looper), LifecycleObserver {
init {
lifecycleOwner.lifecycle.addObserver(this)
}
@OnLifecycleEvent(Lifecycle.Event.ON_DESTROY)
fun onDestroy() {
removeCallbacksAndMessages(null)
lifecycleOwner.lifecycle.removeObserver(this)
}
}

View File

@ -1,35 +0,0 @@
package com.quyunshuo.base.livedata
import androidx.lifecycle.LifecycleOwner
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.Observer
import java.util.concurrent.atomic.AtomicBoolean
/**
* @Author: QuYunShuo
* @Time: 2020/9/17
* @Class: OnceLiveData
* @Remark: 只执行一次的LiveData
*/
class OnceLiveData<T> : MutableLiveData<T>() {
private var isRead: AtomicBoolean = AtomicBoolean(false)
override fun observe(owner: LifecycleOwner, observer: Observer<in T>) {
super.observe(owner, Observer {
if (isRead.compareAndSet(false, true)) {
observer.onChanged(it)
}
})
}
override fun postValue(value: T) {
isRead.set(false)
super.postValue(value)
}
override fun setValue(value: T) {
isRead.set(false)
super.setValue(value)
}
}

View File

@ -1 +0,0 @@
<manifest package="com.quyunshuo.common" />

View File

@ -1,101 +0,0 @@
package com.quyunshuo.common
import android.app.Activity
import android.app.Application
import android.os.Bundle
import com.alibaba.android.arouter.launcher.ARouter
import com.quyunshuo.base.BaseApplication
import com.quyunshuo.base.BaseApplication.InitDepend
import com.quyunshuo.base.utils.ActivityStackManager
import com.quyunshuo.base.utils.ProcessUtils
import com.quyunshuo.base.utils.SpUtils
import com.tencent.bugly.crashreport.CrashReport
/**
* @Author: QuYunShuo
* @Time: 2020/8/27
* @Class: CommonApplication
* @Remark: 项目相关的Application
*/
open class CommonApplication : BaseApplication(), Application.ActivityLifecycleCallbacks {
/**
* 项目当前的版本状态
*/
val versionStatus: String by lazy { getString(R.string.VERSION_STATUS) }
override fun onCreate() {
super.onCreate()
// 全局监听 Activity 生命周期
registerActivityLifecycleCallbacks(this)
}
/**
* 需要立即进行初始化的放在这里进行并行初始化
* 需要必须在主线程初始化的放在[InitDepend.mainThreadDepends],反之放在[InitDepend.workerThreadDepends]
* @return InitDepend 初始化方法集合
*/
override fun initByFrontDesk(): InitDepend {
val worker = mutableListOf<() -> String>()
// 以下只需要在主进程当中初始化 按需要调整
if (ProcessUtils.isMainProcess(this)) {
worker.add { initMMKV() }
worker.add { initARouter() }
}
worker.add { initTencentBugly() }
return InitDepend(null, worker)
}
/**
* 不需要立马初始化的放在这里进行后台初始化
*/
override suspend fun initByBackstage() {}
/**
* 腾讯 MMKV 初始化
*/
private fun initMMKV(): String {
val result = SpUtils.initMMKV(this)
return "MMKV -->> $result"
}
/**
* 阿里路由 ARouter 初始化
*/
private fun initARouter(): String {
// 测试环境下打开ARouter的日志和调试模式 正式环境需要关闭
if (versionStatus == "VERSION_STATUS_ALPHA" || versionStatus == "VERSION_STATUS_BETA") {
ARouter.openLog() // 打印日志
ARouter.openDebug() // 开启调试模式(如果在InstantRun模式下运行必须开启调试模式线上版本需要关闭,否则有安全风险)
}
ARouter.init(this)
return "ARouter -->> init complete"
}
/**
* 初始化 腾讯Bugly
* 测试环境应该与正式环境的日志收集渠道分隔开
*/
private fun initTencentBugly(): String {
// 第三个参数为SDK调试模式开关
CrashReport.initCrashReport(
this,
getString(R.string.BUGLY_APP_ID),
versionStatus == "VERSION_STATUS_ALPHA" || versionStatus == "VERSION_STATUS_BETA"
)
return "Bugly -->> init complete"
}
override fun onActivityCreated(activity: Activity, bundle: Bundle?) {
ActivityStackManager.addActivityToStack(activity)
}
override fun onActivityStarted(activity: Activity) {}
override fun onActivityResumed(activity: Activity) {}
override fun onActivityPaused(activity: Activity) {}
override fun onActivityStopped(activity: Activity) {}
override fun onActivitySaveInstanceState(activity: Activity, bundle: Bundle) {}
override fun onActivityDestroyed(activity: Activity) {
ActivityStackManager.popActivityToStack(activity)
}
}

View File

@ -1,9 +0,0 @@
package com.quyunshuo.common.constant
/**
* @Author: QuYunShuo
* @Time: 2020/8/29
* @Class: NetUrl
* @Remark: 请求公共地址 统一放在此类
*/
object NetUrl

View File

@ -1,17 +0,0 @@
package com.quyunshuo.common.net
import com.quyunshuo.common.net.api.ApiCommonService
/**
* @Author: QuYunShuo
* @Time: 2020/8/29
* @Class: NetRequest
* @Remark: 对ApiService动态代理对象统一管理
*/
object NetRequest {
// 公共接口
val commonService by lazy(mode = LazyThreadSafetyMode.NONE) {
NetServiceCreator.create(ApiCommonService::class.java)
}
}

View File

@ -1,61 +0,0 @@
package com.quyunshuo.common.net
import com.quyunshuo.base.BaseApplication
import com.quyunshuo.base.BuildConfig
import com.readystatesoftware.chuck.ChuckInterceptor
import okhttp3.OkHttpClient
import okhttp3.logging.HttpLoggingInterceptor
import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory
import java.util.concurrent.TimeUnit
/**
* @Author: QuYunShuo
* @Time: 2020/8/29
* @Class: NetServiceCreator
* @Remark: Retrofit动态代理对象获取封装
*/
object NetServiceCreator {
private const val CONNECT_TIME_OUT = 15L
private const val READ_TIME_OUT = 20L
private val BODY by lazy(mode = LazyThreadSafetyMode.NONE) {
HttpLoggingInterceptor().setLevel(HttpLoggingInterceptor.Level.BODY)
}
private val NONE by lazy(mode = LazyThreadSafetyMode.NONE) {
HttpLoggingInterceptor().setLevel(HttpLoggingInterceptor.Level.NONE)
}
private val okHttpClient by lazy(mode = LazyThreadSafetyMode.SYNCHRONIZED) {
OkHttpClient.Builder()
.connectTimeout(CONNECT_TIME_OUT, TimeUnit.SECONDS) // 连接超时
.readTimeout(READ_TIME_OUT, TimeUnit.SECONDS) // 读取超时
.addInterceptor(if (BuildConfig.DEBUG) BODY else NONE) // 请求日志拦截器
.addInterceptor(ChuckInterceptor(BaseApplication.context)) // 请求日志拦截器(UI)
.retryOnConnectionFailure(true) // 失败重连
.build()
}
private val retrofit by lazy(mode = LazyThreadSafetyMode.SYNCHRONIZED) {
Retrofit.Builder()
.baseUrl("")
.addConverterFactory(GsonConverterFactory.create()) // Gson转换器
.client(okHttpClient)
.build()
}
/**
* 获取service动态代理对象
* @param serviceClass 接口Class对象
*/
fun <T> create(serviceClass: Class<T>): T = retrofit.create(serviceClass)
/**
* 获取service动态代理对象
* 范型实化
*/
inline fun <reified T> create(): T = create(T::class.java)
}

View File

@ -1,9 +0,0 @@
package com.quyunshuo.common.net.api
/**
* @Author: QuYunShuo
* @Time: 2020/8/29
* @Class: ApiCommonService
* @Remark: 公共接口
*/
interface ApiCommonService

View File

@ -1,5 +1,7 @@
# <p align="center"> AndroidBaseFrameMVVM 🐽</p>
## 框架已进行部分重构暂未编写文档及示例demo等有时间后会根据当前框架编写新的文档及示例demo本文档目前不是最新的
<p align="center"> AndroidBaseFrameMVVM 是一个 Android 项目 MVVM 架构 开箱即用的框架 </p>
<p align="center"> 该框架基于 Kotlin + Flow + Jetpack + MVVM + 组件化 + Repository 模式实现</p>

1
app/build.gradle.kts Normal file
View File

@ -0,0 +1 @@
apply("../buildGradleScript/app.gradle")

View File

@ -12,7 +12,6 @@
tools:ignore="ProtectedPermissions" />
<application
android:name=".AppApplication"
android:allowBackup="false"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
@ -29,6 +28,7 @@
<meta-data
android:name="design_height_in_dp"
android:value="640" />
</application>
</manifest>

View File

@ -1,22 +0,0 @@
package com.quyunshuo.androidbaseframemvvm
import com.quyunshuo.common.CommonApplication
import org.greenrobot.eventbus.EventBus
/**
* @Author: QuYunShuo
* @Time: 2020/8/27
* @Class: AppApplication
* @Remark: 壳App的Application 负责需要写在App包下的初始化逻辑
*/
class AppApplication : CommonApplication() {
override fun onCreate() {
// 开启EventBusAPT,优化反射效率
EventBus
.builder()
// .addIndex()
.installDefaultEventBus()
super.onCreate()
}
}

View File

@ -0,0 +1,54 @@
package com.quyunshuo.androidbaseframemvvm.app
import android.app.Application
import android.content.Context
import com.google.auto.service.AutoService
import com.quyunshuo.androidbaseframemvvm.base.app.ApplicationLifecycle
import com.quyunshuo.androidbaseframemvvm.base.app.InitDepend
import org.greenrobot.eventbus.EventBus
/**
* App壳
*
* @author Qu Yunshuo
* @since 4/23/21 6:08 PM
*/
@AutoService(ApplicationLifecycle::class)
class AppApplication : ApplicationLifecycle {
/**
* 同[Application.attachBaseContext]
* @param context Context
*/
override fun onAttachBaseContext(context: Context) {
// 开启EventBusAPT,优化反射效率 当组件作为App运行时需要将添加的Index注释掉 因为找不到对应的类了
EventBus
.builder()
// .addIndex(MainEventIndex())
.installDefaultEventBus()
}
/**
* 同[Application.onCreate]
* @param application Application
*/
override fun onCreate(application: Application) {}
/**
* 同[Application.onTerminate]
* @param application Application
*/
override fun onTerminate(application: Application) {}
/**
* 需要立即进行初始化的放在这里进行并行初始化
* 需要必须在主线程初始化的放在[InitDepend.mainThreadDepends],反之放在[InitDepend.workerThreadDepends]
* @return InitDepend 初始化方法集合
*/
override fun initByFrontDesk(): InitDepend = InitDepend(mutableListOf(), mutableListOf())
/**
* 不需要立即初始化的放在这里进行后台初始化
*/
override fun initByBackstage() {}
}

View File

@ -1,4 +1,4 @@
import com.quyunshuo.androidbaseframemvvm.build.*
import com.quyunshuo.androidbaseframemvvm.buildsrc.*
buildscript {
repositories {

View File

@ -1,10 +1,13 @@
import com.quyunshuo.androidbaseframemvvm.build.*
//****************************************
//************ app ************
//****************************************
plugins {
id 'com.android.application'
id 'kotlin-android'
id 'com.alibaba.arouter'
}
import com.quyunshuo.androidbaseframemvvm.buildsrc.*
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: 'com.alibaba.arouter'
apply plugin: 'kotlin-kapt'
android {
compileSdkVersion ProjectBuildConfig.compileSdkVersion
@ -16,8 +19,14 @@ android {
targetSdkVersion ProjectBuildConfig.targetSdkVersion
versionCode ProjectBuildConfig.versionCode
versionName ProjectBuildConfig.versionName
testInstrumentationRunner AndroidX.AndroidJUnitRunner
testInstrumentationRunner DependencyConfig.AndroidX.AndroidJUnitRunner
multiDexKeepProguard file("multidexKeep.pro")
ndk {
// SO库架构
//abiFilters 'armeabi', 'x86', 'armeabi-v7a', 'x86_64', 'arm64-v8a'
abiFilters 'armeabi-v7a', 'arm64-v8a', 'x86'
}
}
// signingConfigs {
@ -39,7 +48,9 @@ android {
if (outputFileName != null
&& outputFileName.endsWith('.apk')
&& 'release' == variant.buildType.name) {
outputFileName = "${ProjectBuildConfig.applicationId}_${defaultConfig.versionCode}(${defaultConfig.versionName}).apk"
outputFileName = "${ProjectBuildConfig.applicationId}" +
"_${ProjectBuildConfig.versionCode}" +
"(${ProjectBuildConfig.versionName}).apk"
}
}
}
@ -52,7 +63,9 @@ android {
if (outputFileName != null
&& outputFileName.endsWith('.apk')
&& 'debug' == variant.buildType.name) {
outputFileName = "${ProjectBuildConfig.applicationId}_${defaultConfig.versionCode}(${defaultConfig.versionName}).apk"
outputFileName = "${ProjectBuildConfig.applicationId}" +
"_${ProjectBuildConfig.versionCode}" +
"(${ProjectBuildConfig.versionName}).apk"
}
}
}
@ -65,16 +78,18 @@ android {
}
kotlinOptions {
jvmTarget = JavaVersion.VERSION_1_8.toString()
jvmTarget = '1.8'
}
}
dependencies {
implementation fileTree(dir: "libs", include: ["*.jar"])
if (!ProjectBuildConfig.isAppMode) {
// 使base里的依赖库
implementation project(path: ':Lib_Common')
implementation project(path: ':lib_common')
} else {
implementation project(path: ':Lib_Common')
implementation project(path: ':lib_common')
}
kapt DependencyConfig.GitHub.AutoServiceAnnotations
}

View File

@ -1,10 +1,12 @@
import com.quyunshuo.androidbaseframemvvm.build.*
//****************************************
//********* lib **********
//****************************************
plugins {
id 'com.android.library'
id 'kotlin-android'
id 'kotlin-kapt'
}
import com.quyunshuo.androidbaseframemvvm.buildsrc.*
apply plugin: 'com.android.library'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-kapt'
android {
compileSdkVersion ProjectBuildConfig.compileSdkVersion
@ -15,12 +17,14 @@ android {
targetSdkVersion ProjectBuildConfig.targetSdkVersion
versionCode ProjectBuildConfig.versionCode
versionName ProjectBuildConfig.versionName
testInstrumentationRunner AndroidX.AndroidJUnitRunner
consumerProguardFiles "consumer-rules.pro"
//
resValue "string", "VERSION_STATUS", ProjectBuildConfig.versionStatus
resValue "string", "BUGLY_APP_ID", SDKKeyConfig.BUGLY_APP_ID
ndk {
// SO库架构
//abiFilters 'armeabi', 'x86', 'armeabi-v7a', 'x86_64', 'arm64-v8a'
abiFilters 'armeabi-v7a', 'arm64-v8a', 'x86'
}
}
compileOptions {
@ -31,8 +35,6 @@ android {
kotlinOptions {
jvmTarget = JavaVersion.VERSION_1_8.toString()
}
resourcePrefix "common_"
}
kapt {
@ -40,13 +42,3 @@ kapt {
arg("AROUTER_MODULE_NAME", project.getName())
}
}
dependencies {
implementation fileTree(dir: "libs", include: ["*.jar"])
api project(path: ':Lib_Base')
kapt GitHub.GlideCompiler
kapt GitHub.ARouteCompiler
kapt GitHub.EventBusAPT
}

View File

@ -1,10 +1,10 @@
import com.quyunshuo.androidbaseframemvvm.build.*
//****************************************
//******** module模块的公共脚本配置 *********
//****************************************
import com.quyunshuo.androidbaseframemvvm.buildsrc.*
if (ProjectBuildConfig.isAppMode) {
apply plugin: 'com.android.application'
} else {
apply plugin: 'com.android.library'
}
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-kapt'
@ -17,7 +17,13 @@ android {
targetSdkVersion ProjectBuildConfig.targetSdkVersion
versionCode ProjectBuildConfig.versionCode
versionName ProjectBuildConfig.versionName
testInstrumentationRunner AndroidX.AndroidJUnitRunner
testInstrumentationRunner DependencyConfig.AndroidX.AndroidJUnitRunner
ndk {
// SO库架构
//abiFilters 'armeabi', 'x86', 'armeabi-v7a', 'x86_64', 'arm64-v8a'
abiFilters 'armeabi-v7a', 'arm64-v8a', 'x86'
}
}
compileOptions {
@ -33,12 +39,8 @@ android {
viewBinding = true
}
//AndroidManifest文件
sourceSets {
main {
if (ProjectBuildConfig.isAppMode) {
manifest.srcFile 'src/main/java/debug/AndroidManifest.xml'
} else {
manifest.srcFile 'src/main/AndroidManifest.xml'
java {
//debug文件夹下的所有文件
@ -46,7 +48,6 @@ android {
}
}
}
}
buildTypes {
release {
@ -63,19 +64,20 @@ android {
kapt {
arguments {
arg("AROUTER_MODULE_NAME", project.name)
arg("eventBusIndex", "${ProjectBuildConfig.applicationId}.eventbus.index.${project.name.replace('Lib_', '')}EventIndex")
arg("eventBusIndex", "${ProjectBuildConfig.applicationId}.eventbus.index.${project.name}EventIndex")
}
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
api project(path: ':Lib_Common')
api project(path: ':lib_common')
testImplementation Android.Junit
androidTestImplementation AndroidX.TestExtJunit
androidTestImplementation AndroidX.TestEspresso
kapt GitHub.GlideCompiler
kapt GitHub.ARouteCompiler
kapt GitHub.EventBusAPT
testImplementation DependencyConfig.Android.Junit
androidTestImplementation DependencyConfig.AndroidX.TestExtJunit
androidTestImplementation DependencyConfig.AndroidX.TestEspresso
kapt DependencyConfig.GitHub.GlideCompiler
kapt DependencyConfig.GitHub.ARouteCompiler
kapt DependencyConfig.GitHub.EventBusAPT
kapt DependencyConfig.GitHub.AutoServiceAnnotations
}

View File

@ -0,0 +1,59 @@
//****************************************
//********** lib_base 的配置文件 ***********
//****************************************
apply from: '../buildGradleScript/base/base_lib.gradle'
import com.quyunshuo.androidbaseframemvvm.buildsrc.*
android {
buildFeatures {
viewBinding = true
}
resourcePrefix "base_"
}
dependencies {
implementation fileTree(dir: "libs", include: ["*.jar"])
api DependencyConfig.AndroidX.CoreKtx
api DependencyConfig.AndroidX.AppCompat
api DependencyConfig.AndroidX.ConstraintLayout
api DependencyConfig.AndroidX.ActivityKtx
api DependencyConfig.AndroidX.FragmentKtx
api DependencyConfig.AndroidX.MultiDex
api DependencyConfig.Android.Material
api DependencyConfig.Kotlin.Kotlin
api DependencyConfig.Kotlin.CoroutinesCore
api DependencyConfig.Kotlin.CoroutinesAndroid
api DependencyConfig.JetPack.LifecycleRuntimeKtx
api DependencyConfig.JetPack.LifecycleViewModel
api DependencyConfig.JetPack.LifecycleViewModelKtx
api DependencyConfig.GitHub.Gson
api DependencyConfig.GitHub.MMKV
api DependencyConfig.GitHub.AutoSize
api DependencyConfig.GitHub.Glide
api DependencyConfig.GitHub.ARoute
api DependencyConfig.GitHub.RecyclerViewAdapter
api DependencyConfig.GitHub.StatusBar
api DependencyConfig.GitHub.EventBus
api DependencyConfig.GitHub.PermissionX
api DependencyConfig.GitHub.AutoService
api DependencyConfig.SDK.TencentBugly
api DependencyConfig.SDK.TencentBuglyNative
api DependencyConfig.SDK.TencentTBSX5
kapt DependencyConfig.GitHub.GlideCompiler
kapt DependencyConfig.GitHub.ARouteCompiler
kapt DependencyConfig.GitHub.EventBusAPT
kapt DependencyConfig.GitHub.AutoServiceAnnotations
debugApi DependencyConfig.GitHub.LeakCanary
}

View File

@ -0,0 +1,34 @@
//****************************************
//********* lib_common 的配置文件 **********
//****************************************
apply from: '../buildGradleScript/base/base_lib.gradle'
import com.quyunshuo.androidbaseframemvvm.buildsrc.*
android {
defaultConfig {
// 相关自定义配置
resValue "string", "VERSION_STATUS", ProjectBuildConfig.versionStatus
resValue "string", "BUGLY_APP_ID", SDKKeyConfig.BUGLY_APP_ID
}
buildFeatures {
viewBinding = true
}
resourcePrefix "common_"
}
dependencies {
implementation fileTree(dir: "libs", include: ["*.jar"])
api project(path: ':lib_base')
api project(path: ':lib_net')
kapt DependencyConfig.GitHub.GlideCompiler
kapt DependencyConfig.GitHub.ARouteCompiler
kapt DependencyConfig.GitHub.EventBusAPT
kapt DependencyConfig.GitHub.AutoServiceAnnotations
}

View File

@ -0,0 +1,24 @@
//****************************************
//*********** lib_net 的配置文件 ***********
//****************************************
apply from: '../buildGradleScript/base/base_lib.gradle'
import com.quyunshuo.androidbaseframemvvm.buildsrc.*
android {
resourcePrefix "net_"
}
dependencies {
implementation fileTree(dir: "libs", include: ["*.jar"])
implementation project(path: ':lib_base')
api DependencyConfig.GitHub.OkHttp
api DependencyConfig.GitHub.OkHttpInterceptorLogging
api DependencyConfig.GitHub.Retrofit
api DependencyConfig.GitHub.RetrofitConverterGson
kapt DependencyConfig.GitHub.AutoServiceAnnotations
}

View File

@ -0,0 +1,9 @@
//****************************************
//******** module_home 的配置文件 *********
//****************************************
apply from: '../buildGradleScript/base/base_module.gradle'
android {
resourcePrefix "home_"
}

View File

@ -1,108 +0,0 @@
package com.quyunshuo.androidbaseframemvvm.build
/**
* 依赖库管理
*/
object Version {
// AndroidX--------------------------------------------------------------
const val AppCompat = "1.2.0"
const val CoreKtx = "1.3.1"
const val ConstraintLayout = "2.0.1" // 约束布局
const val TestExtJunit = "1.1.2"
const val TestEspresso = "3.3.0"
const val ActivityKtx = "1.1.0"
const val FragmentKtx = "1.2.5"
const val MultiDex = "2.0.1"
// Android---------------------------------------------------------------
const val Junit = "4.13"
// Kotlin----------------------------------------------------------------
const val Kotlin = "1.4.31" // Kotlin
const val Coroutines = "1.4.3" // 协程
// JetPack---------------------------------------------------------------
const val LifecycleViewModel = "2.2.0"
const val LifecycleRuntimeKtx = "2.2.0"
const val LifecycleViewModelKtx = "2.2.0"
// GitHub----------------------------------------------------------------
const val OkHttp = "3.14.9" // OkHttp
const val OkHttpInterceptorLogging = "3.12.0" // OkHttp 请求Log拦截器
const val Retrofit = "2.9.0" // Retrofit
const val RetrofitConverterGson = "2.9.0" // Retrofit Gson 转换器
const val Gson = "2.8.6" // Gson
const val MMKV = "1.2.2" // 腾讯 MMKV 替代SP
const val AutoSize = "1.2.1" // 屏幕适配
const val Glide = "4.11.0" // Glide
const val ARoute = "1.5.1" // 阿里路由
const val ARouteCompiler = "1.5.1" // 阿里路由 APT
const val RecyclerViewAdapter = "3.0.4" // RecyclerViewAdapter
const val StatusBar = "1.5.1" // 状态栏
const val EventBus = "3.2.0" // 事件总线
const val Bugly = "3.3.7" // Bugly 异常上报
const val BuglyNative = "3.8.0" // Bugly native异常上报
const val PermissionX = "1.3.0" // 权限申请
const val LeakCanary = "2.4" // 检测内存泄漏
const val Chuck = "1.1.0" // OkHttp 请求信息拦截器(UI)
}
object AndroidX {
const val AndroidJUnitRunner = "androidx.test.runner.AndroidJUnitRunner"
const val AppCompat = "androidx.appcompat:appcompat:${Version.AppCompat}"
const val CoreKtx = "androidx.core:core-ktx:${Version.CoreKtx}"
const val ConstraintLayout =
"androidx.constraintlayout:constraintlayout:${Version.ConstraintLayout}"
const val TestExtJunit = "androidx.test.ext:junit:${Version.TestExtJunit}"
const val TestEspresso = "androidx.test.espresso:espresso-core:${Version.TestEspresso}"
const val ActivityKtx = "androidx.activity:activity-ktx:${Version.ActivityKtx}"
const val FragmentKtx = "androidx.fragment:fragment-ktx:${Version.FragmentKtx}"
const val MultiDex = "androidx.multidex:multidex:${Version.MultiDex}"
}
object Android {
const val Junit = "junit:junit:${Version.Junit}"
}
object JetPack {
const val LifecycleViewModel =
"androidx.lifecycle:lifecycle-viewmodel:${Version.LifecycleViewModel}"
const val LifecycleRuntimeKtx =
"androidx.lifecycle:lifecycle-runtime-ktx:${Version.LifecycleRuntimeKtx}"
const val LifecycleViewModelKtx =
"androidx.lifecycle:lifecycle-viewmodel-ktx:${Version.LifecycleViewModelKtx}"
}
object Kotlin {
const val Kotlin = "org.jetbrains.kotlin:kotlin-stdlib:${Version.Kotlin}"
const val CoroutinesCore = "org.jetbrains.kotlinx:kotlinx-coroutines-core:${Version.Coroutines}"
const val CoroutinesAndroid =
"org.jetbrains.kotlinx:kotlinx-coroutines-android:${Version.Coroutines}"
}
object GitHub {
const val OkHttp = "com.squareup.okhttp3:okhttp:${Version.OkHttp}"
const val OkHttpInterceptorLogging =
"com.squareup.okhttp3:logging-interceptor:${Version.OkHttpInterceptorLogging}"
const val Retrofit = "com.squareup.retrofit2:retrofit:${Version.Retrofit}"
const val RetrofitConverterGson =
"com.squareup.retrofit2:converter-gson:${Version.RetrofitConverterGson}"
const val Gson = "com.google.code.gson:gson:${Version.Gson}"
const val MMKV = "com.tencent:mmkv-static:${Version.MMKV}"
const val AutoSize = "me.jessyan:autosize:${Version.AutoSize}"
const val Glide = "com.github.bumptech.glide:glide:${Version.Glide}"
const val GlideCompiler = "com.github.bumptech.glide:compiler:${Version.Glide}"
const val ARoute = "com.alibaba:arouter-api:${Version.ARoute}"
const val ARouteCompiler = "com.alibaba:arouter-compiler:${Version.ARouteCompiler}"
const val RecyclerViewAdapter =
"com.github.CymChad:BaseRecyclerViewAdapterHelper:${Version.RecyclerViewAdapter}"
const val StatusBar = "com.jaeger.statusbarutil:library:${Version.StatusBar}"
const val EventBus = "org.greenrobot:eventbus:${Version.EventBus}"
const val EventBusAPT = "org.greenrobot:eventbus-annotation-processor:${Version.EventBus}"
const val Bugly = "com.tencent.bugly:crashreport:${Version.Bugly}"
const val BuglyNative = "com.tencent.bugly:nativecrashreport:${Version.BuglyNative}"
const val PermissionX = "com.permissionx.guolindev:permissionx:${Version.PermissionX}"
const val LeakCanary = "com.squareup.leakcanary:leakcanary-android:${Version.LeakCanary}"
const val Chuck = "com.readystatesoftware.chuck:library:${Version.Chuck}"
const val ChuckNo = "com.readystatesoftware.chuck:library-no-op:${Version.Chuck}"
}

View File

@ -0,0 +1,158 @@
package com.quyunshuo.androidbaseframemvvm.buildsrc
/**
* 项目依赖版本统一管理
*
* @author Qu Yunshuo
* @since 4/24/21 4:00 PM
*/
object DependencyConfig {
/**
* 依赖版本号
*
* @author Qu Yunshuo
* @since 4/24/21 4:01 PM
*/
object Version {
// AndroidX--------------------------------------------------------------
const val AppCompat = "1.2.0"
const val CoreKtx = "1.3.1"
const val ConstraintLayout = "2.0.1" // 约束布局
const val TestExtJunit = "1.1.2"
const val TestEspresso = "3.3.0"
const val ActivityKtx = "1.1.0"
const val FragmentKtx = "1.2.5"
const val MultiDex = "2.0.1"
// Android---------------------------------------------------------------
const val Junit = "4.13"
const val Material = "1.2.0" // 材料设计UI套件
// Kotlin----------------------------------------------------------------
const val Kotlin = "1.4.32"
const val Coroutines = "1.4.3" // 协程
// JetPack---------------------------------------------------------------
const val LifecycleViewModel = "2.2.0"
const val LifecycleRuntimeKtx = "2.2.0"
const val LifecycleViewModelKtx = "2.2.0"
// GitHub----------------------------------------------------------------
const val OkHttp = "3.14.9" // OkHttp
const val OkHttpInterceptorLogging = "3.12.0" // OkHttp 请求Log拦截器
const val Retrofit = "2.9.0" // Retrofit
const val RetrofitConverterGson = "2.9.0" // Retrofit Gson 转换器
const val Gson = "2.8.6" // Gson
const val MMKV = "1.2.2" // 腾讯 MMKV 替代SP
const val AutoSize = "1.2.1" // 屏幕适配
const val Glide = "4.11.0" // Glide
const val ARoute = "1.5.1" // 阿里路由
const val ARouteCompiler = "1.5.1" // 阿里路由 APT
const val RecyclerViewAdapter = "3.0.4" // RecyclerViewAdapter
const val StatusBar = "1.5.1" // 状态栏
const val EventBus = "3.2.0" // 事件总线
const val PermissionX = "1.3.0" // 权限申请
const val LeakCanary = "2.4" // 检测内存泄漏
const val AutoService = "1.0" // 自动生成SPI暴露服务文件
// 第三方SDK--------------------------------------------------------------
const val TencentBugly = "3.3.7" // 腾讯Bugly 异常上报
const val TencentBuglyNative = "3.8.0" // Bugly native异常上报
const val TencentTBSX5 = "43939" // 腾讯X5WebView
}
/**
* AndroidX相关依赖
*
* @author Qu Yunshuo
* @since 4/24/21 4:01 PM
*/
object AndroidX {
const val AndroidJUnitRunner = "androidx.test.runner.AndroidJUnitRunner"
const val AppCompat = "androidx.appcompat:appcompat:${Version.AppCompat}"
const val CoreKtx = "androidx.core:core-ktx:${Version.CoreKtx}"
const val ConstraintLayout = "androidx.constraintlayout:constraintlayout:${Version.ConstraintLayout}"
const val TestExtJunit = "androidx.test.ext:junit:${Version.TestExtJunit}"
const val TestEspresso = "androidx.test.espresso:espresso-core:${Version.TestEspresso}"
const val ActivityKtx = "androidx.activity:activity-ktx:${Version.ActivityKtx}"
const val FragmentKtx = "androidx.fragment:fragment-ktx:${Version.FragmentKtx}"
const val MultiDex = "androidx.multidex:multidex:${Version.MultiDex}"
}
/**
* Android相关依赖
*
* @author Qu Yunshuo
* @since 4/24/21 4:02 PM
*/
object Android {
const val Junit = "junit:junit:${Version.Junit}"
const val Material = "com.google.android.material:material:${Version.Material}"
}
/**
* JetPack相关依赖
*
* @author Qu Yunshuo
* @since 4/24/21 4:02 PM
*/
object JetPack {
const val LifecycleViewModel = "androidx.lifecycle:lifecycle-viewmodel:${Version.LifecycleViewModel}"
const val LifecycleRuntimeKtx = "androidx.lifecycle:lifecycle-runtime-ktx:${Version.LifecycleRuntimeKtx}"
const val LifecycleViewModelKtx = "androidx.lifecycle:lifecycle-viewmodel-ktx:${Version.LifecycleViewModelKtx}"
}
/**
* Kotlin相关依赖
*
* @author Qu Yunshuo
* @since 4/24/21 4:02 PM
*/
object Kotlin {
const val Kotlin = "org.jetbrains.kotlin:kotlin-stdlib:${Version.Kotlin}"
const val CoroutinesCore = "org.jetbrains.kotlinx:kotlinx-coroutines-core:${Version.Coroutines}"
const val CoroutinesAndroid = "org.jetbrains.kotlinx:kotlinx-coroutines-android:${Version.Coroutines}"
}
/**
* GitHub及其他相关依赖
*
* @author Qu Yunshuo
* @since 4/24/21 4:02 PM
*/
object GitHub {
const val OkHttp = "com.squareup.okhttp3:okhttp:${Version.OkHttp}"
const val OkHttpInterceptorLogging = "com.squareup.okhttp3:logging-interceptor:${Version.OkHttpInterceptorLogging}"
const val Retrofit = "com.squareup.retrofit2:retrofit:${Version.Retrofit}"
const val RetrofitConverterGson = "com.squareup.retrofit2:converter-gson:${Version.RetrofitConverterGson}"
const val Gson = "com.google.code.gson:gson:${Version.Gson}"
const val MMKV = "com.tencent:mmkv-static:${Version.MMKV}"
const val AutoSize = "me.jessyan:autosize:${Version.AutoSize}"
const val Glide = "com.github.bumptech.glide:glide:${Version.Glide}"
const val GlideCompiler = "com.github.bumptech.glide:compiler:${Version.Glide}"
const val ARoute = "com.alibaba:arouter-api:${Version.ARoute}"
const val ARouteCompiler = "com.alibaba:arouter-compiler:${Version.ARouteCompiler}"
const val RecyclerViewAdapter = "com.github.CymChad:BaseRecyclerViewAdapterHelper:${Version.RecyclerViewAdapter}"
const val StatusBar = "com.jaeger.statusbarutil:library:${Version.StatusBar}"
const val EventBus = "org.greenrobot:eventbus:${Version.EventBus}"
const val EventBusAPT = "org.greenrobot:eventbus-annotation-processor:${Version.EventBus}"
const val PermissionX = "com.permissionx.guolindev:permissionx:${Version.PermissionX}"
const val LeakCanary = "com.squareup.leakcanary:leakcanary-android:${Version.LeakCanary}"
const val AutoService = "com.google.auto.service:auto-service:${Version.AutoService}"
const val AutoServiceAnnotations = "com.google.auto.service:auto-service-annotations:${Version.AutoService}"
}
/**
* SDK相关依赖
*
* @author Qu Yunshuo
* @since 4/24/21 4:02 PM
*/
object SDK {
const val TencentBugly = "com.tencent.bugly:crashreport:${Version.TencentBugly}"
const val TencentBuglyNative = "com.tencent.bugly:nativecrashreport:${Version.TencentBuglyNative}"
const val TencentTBSX5 = "com.tencent.tbs.tbssdk:sdk:${Version.TencentTBSX5}"
}
}

View File

@ -1,7 +1,10 @@
package com.quyunshuo.androidbaseframemvvm.build
package com.quyunshuo.androidbaseframemvvm.buildsrc
/**
* 项目相关参数配置
*
* @author Qu Yunshuo
* @since 4/24/21 5:56 PM
*/
object ProjectBuildConfig {
const val compileSdkVersion = 30

View File

@ -1,10 +1,13 @@
package com.quyunshuo.androidbaseframemvvm.build
package com.quyunshuo.androidbaseframemvvm.buildsrc
/**
* 项目级插件管理
*
* @author Qu Yunshuo
* @since 4/24/21 5:56 PM
*/
object ProjectPluginManager {
const val AndroidToolsPlugin = "com.android.tools.build:gradle:4.1.2"
const val KotlinPlugin = "org.jetbrains.kotlin:kotlin-gradle-plugin:1.4.31"
const val KotlinPlugin = "org.jetbrains.kotlin:kotlin-gradle-plugin:1.4.32"
const val ARouterRegister = "com.alibaba:arouter-register:1.0.2"
}

View File

@ -1,7 +1,8 @@
package com.quyunshuo.androidbaseframemvvm.build
package com.quyunshuo.androidbaseframemvvm.buildsrc
/**
* 存放需要存在本地的SDK的密钥
* 这种方式并不安全
*/
object SDKKeyConfig {

View File

@ -0,0 +1 @@
apply("../buildGradleScript/lib_base.gradle")

View File

@ -0,0 +1 @@
<manifest package="com.quyunshuo.androidbaseframemvvm.base" />

View File

@ -0,0 +1,48 @@
package com.quyunshuo.androidbaseframemvvm.base.app
import android.app.Activity
import android.app.Application
import android.os.Bundle
import android.util.Log
import com.quyunshuo.androidbaseframemvvm.base.utils.ActivityStackManager
/**
* Activity生命周期监听
*
* @author Qu Yunshuo
* @since 4/20/21 9:10 AM
*/
class ActivityLifecycleCallbacksImpl : Application.ActivityLifecycleCallbacks {
private val TAG = "ActivityLifecycle"
override fun onActivityCreated(activity: Activity, bundle: Bundle?) {
ActivityStackManager.addActivityToStack(activity)
Log.e(TAG, "${activity.javaClass.simpleName} --> onActivityCreated")
}
override fun onActivityStarted(activity: Activity) {
Log.e(TAG, "${activity.javaClass.simpleName} --> onActivityStarted")
}
override fun onActivityResumed(activity: Activity) {
Log.e(TAG, "${activity.javaClass.simpleName} --> onActivityResumed")
}
override fun onActivityPaused(activity: Activity) {
Log.e(TAG, "${activity.javaClass.simpleName} --> onActivityPaused")
}
override fun onActivityStopped(activity: Activity) {
Log.e(TAG, "${activity.javaClass.simpleName} --> onActivityStopped")
}
override fun onActivitySaveInstanceState(activity: Activity, outState: Bundle) {
Log.e(TAG, "${activity.javaClass.simpleName} --> onActivitySaveInstanceState")
}
override fun onActivityDestroyed(activity: Activity) {
ActivityStackManager.popActivityToStack(activity)
Log.e(TAG, "${activity.javaClass.simpleName} --> onActivityDestroyed")
}
}

View File

@ -0,0 +1,43 @@
package com.quyunshuo.androidbaseframemvvm.base.app
import android.app.Application
import android.content.Context
/**
* Application 生命周期 用于初始化各个组件
*
* @author Qu Yunshuo
* @since 4/23/21 5:22 PM
*/
interface ApplicationLifecycle {
/**
* 同[Application.attachBaseContext]
* @param context Context
*/
fun onAttachBaseContext(context: Context)
/**
* 同[Application.onCreate]
* @param application Application
*/
fun onCreate(application: Application)
/**
* 同[Application.onTerminate]
* @param application Application
*/
fun onTerminate(application: Application)
/**
* 需要立即进行初始化的放在这里进行并行初始化
* 需要必须在主线程初始化的放在[InitDepend.mainThreadDepends],反之放在[InitDepend.workerThreadDepends]
* @return InitDepend 初始化方法集合
*/
fun initByFrontDesk(): InitDepend
/**
* 不需要立即初始化的放在这里进行后台初始化
*/
fun initByBackstage()
}

View File

@ -1,4 +1,4 @@
package com.quyunshuo.base
package com.quyunshuo.androidbaseframemvvm.base.app
import android.annotation.SuppressLint
import android.content.Context
@ -8,40 +8,45 @@ import kotlinx.coroutines.*
import kotlin.system.measureTimeMillis
/**
* @Author: QuYunShuo
* @Time: 2020/8/27
* @Class: BaseApplication
* @Remark: 自定义Application的基类
* Application 基类
*
* @author Qu Yunshuo
* @since 4/24/21 5:30 PM
*/
abstract class BaseApplication : MultiDexApplication() {
class BaseApplication : MultiDexApplication() {
private val mCoroutineScope by lazy(mode = LazyThreadSafetyMode.NONE) { MainScope() }
private val mLoadModuleProxy by lazy(mode = LazyThreadSafetyMode.NONE) { LoadModuleProxy() }
companion object {
// 全局Context
@SuppressLint("StaticFieldLeak")
lateinit var context: Context
@SuppressLint("StaticFieldLeak")
lateinit var application: BaseApplication
}
override fun attachBaseContext(base: Context) {
super.attachBaseContext(base)
context = base
application = this
mLoadModuleProxy.onAttachBaseContext(base)
}
override fun onCreate() {
super.onCreate()
context = applicationContext
// 全局监听 Activity 生命周期
registerActivityLifecycleCallbacks(ActivityLifecycleCallbacksImpl())
mLoadModuleProxy.onCreate(this)
// 策略初始化第三方依赖
initDepends()
}
/**
* 需要立即进行初始化的放在这里进行并行初始化
* 需要必须在主线程初始化的放在[InitDepend.mainThreadDepends],反之放在[InitDepend.workerThreadDepends]
* @return InitDepend 初始化方法集合
*/
abstract fun initByFrontDesk(): InitDepend
/**
* 不需要立马初始化的放在这里进行后台初始化
*/
abstract suspend fun initByBackstage()
/**
* 初始化第三方依赖
*
@ -55,18 +60,18 @@ abstract class BaseApplication : MultiDexApplication() {
private fun initDepends() {
// 开启一个 Default Coroutine 进行初始化不会立即使用的第三方
mCoroutineScope.launch(Dispatchers.Default) {
initByBackstage()
mLoadModuleProxy.initByBackstage()
}
// 初始化需要被立即初始化的第三方 多线程并行,并阻塞至全部完成
val measureTimeMillis = measureTimeMillis {
mCoroutineScope.launch(Dispatchers.Main.immediate) {
val depends = initByFrontDesk()
val depends = mLoadModuleProxy.initByFrontDesk()
// 1. 对非必须在主线程初始化的第三方依赖发起并行初始化
// 并行job
var jobs: MutableList<Deferred<String>>? = null
if (depends.workerThreadDepends != null) {
if (depends.workerThreadDepends.isNotEmpty()) {
jobs = mutableListOf()
depends.workerThreadDepends.forEach {
jobs.add(async(Dispatchers.Default) { it() })
@ -74,7 +79,7 @@ abstract class BaseApplication : MultiDexApplication() {
}
// 2. 对必须在主线程初始化的第三方依赖进行初始化
if (depends.mainThreadDepends != null) {
if (depends.mainThreadDepends.isNotEmpty()) {
depends.mainThreadDepends.forEach { it() }
}
@ -85,15 +90,9 @@ abstract class BaseApplication : MultiDexApplication() {
Log.d("ApplicationInit", "初始化完成 $measureTimeMillis ms")
}
/**
* 需要立即进行初始化的依赖列表 有的依赖可能必须要在主线程进行初始化就放在[mainThreadDepends]里面就可以
* 其余的非必须要在主线程进行初始化的放在[workerThreadDepends]里面这部分依赖会被后台线程并行初始化
*
* @property mainThreadDepends MutableList<() -> String>? 必须要在主线程初始化的依赖
* @property workerThreadDepends MutableList<() -> String>? 非必须要在主线程初始化的依赖
*/
data class InitDepend(
val mainThreadDepends: MutableList<() -> String>?,
val workerThreadDepends: MutableList<() -> String>?
)
override fun onTerminate() {
super.onTerminate()
mLoadModuleProxy.onTerminate(this)
mCoroutineScope.cancel()
}
}

View File

@ -0,0 +1,16 @@
package com.quyunshuo.androidbaseframemvvm.base.app
/**
* 需要立即进行初始化的依赖列表 有的依赖可能必须要在主线程进行初始化,就放在[mainThreadDepends]里面就可以
* 其余的非必须要在主线程进行初始化的放在[workerThreadDepends]里面,这部分依赖会被后台线程并行初始化
*
* @property mainThreadDepends MutableList<() -> String> 必须要在主线程初始化的依赖
* @property workerThreadDepends MutableList<() -> String> 非必须要在主线程初始化的依赖
*
* @author Qu Yunshuo
* @since 4/24/21 5:20 PM
*/
data class InitDepend(
val mainThreadDepends: MutableList<() -> String>,
val workerThreadDepends: MutableList<() -> String>
)

View File

@ -0,0 +1,67 @@
package com.quyunshuo.androidbaseframemvvm.base.app
import android.app.Application
import android.content.Context
import android.util.Log
import java.util.*
/**
* 加载组件代理类
* 组件初始化的工作将由该代理类代理实现
*
* @author Qu Yunshuo
* @since 4/23/21 5:37 PM
*/
class LoadModuleProxy : ApplicationLifecycle {
private var mLoader: ServiceLoader<ApplicationLifecycle> =
ServiceLoader.load(ApplicationLifecycle::class.java)
/**
* 同[Application.attachBaseContext]
* @param context Context
*/
override fun onAttachBaseContext(context: Context) {
mLoader.forEach {
Log.d("ApplicationInit", it.toString())
it.onAttachBaseContext(context)
}
}
/**
* 同[Application.onCreate]
* @param application Application
*/
override fun onCreate(application: Application) {
mLoader.forEach { it.onCreate(application) }
}
/**
* 同[Application.onTerminate]
* @param application Application
*/
override fun onTerminate(application: Application) {
mLoader.forEach { it.onTerminate(application) }
}
/**
* 需要立即进行初始化的放在这里进行并行初始化
* @return MutableList<() -> String> 初始化方法的集合
*/
override fun initByFrontDesk(): InitDepend {
val mainThreadDepends: MutableList<() -> String> = mutableListOf()
val workerThreadDepends: MutableList<() -> String> = mutableListOf()
mLoader.forEach {
mainThreadDepends.addAll(it.initByFrontDesk().mainThreadDepends)
workerThreadDepends.addAll(it.initByFrontDesk().workerThreadDepends)
}
return InitDepend(mainThreadDepends, workerThreadDepends)
}
/**
* 不需要立即初始化的放在这里进行后台初始化
*/
override fun initByBackstage() {
mLoader.forEach { it.initByBackstage() }
}
}

View File

@ -0,0 +1,16 @@
package com.quyunshuo.androidbaseframemvvm.base.constant
/**
* 版本状态
*
* @author Qu Yunshuo
* @since 4/20/21 9:05 AM
*/
object VersionStatus {
const val RELEASE = "VERSION_STATUS_RELEASE"
const val ALPHA = "VERSION_STATUS_ALPHA"
const val BETA = "VERSION_STATUS_BETA"
}

View File

@ -1,4 +1,4 @@
package com.quyunshuo.base.ktx
package com.quyunshuo.androidbaseframemvvm.base.ktx
import android.text.InputFilter
import android.widget.EditText

View File

@ -1,4 +1,4 @@
package com.quyunshuo.base.ktx
package com.quyunshuo.androidbaseframemvvm.base.ktx
import android.content.Context
import androidx.fragment.app.Fragment

View File

@ -1,4 +1,4 @@
package com.quyunshuo.base.ktx
package com.quyunshuo.androidbaseframemvvm.base.ktx
import android.animation.Animator
import android.animation.IntEvaluator
@ -7,9 +7,9 @@ import android.annotation.SuppressLint
import android.os.Build
import android.view.View
import android.view.ViewGroup
import com.quyunshuo.base.ktx.ViewClickDelay.SPACE_TIME
import com.quyunshuo.base.ktx.ViewClickDelay.hash
import com.quyunshuo.base.ktx.ViewClickDelay.lastClickTime
import com.quyunshuo.androidbaseframemvvm.base.ktx.ViewClickDelay.SPACE_TIME
import com.quyunshuo.androidbaseframemvvm.base.ktx.ViewClickDelay.hash
import com.quyunshuo.androidbaseframemvvm.base.ktx.ViewClickDelay.lastClickTime
/**
* @Author: QuYunShuo

View File

@ -1,4 +1,4 @@
package com.quyunshuo.base.mvvm.m
package com.quyunshuo.androidbaseframemvvm.base.mvvm.m
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.FlowCollector

View File

@ -1,13 +1,13 @@
package com.quyunshuo.base.mvvm.v
package com.quyunshuo.androidbaseframemvvm.base.mvvm.v
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import androidx.lifecycle.ViewModel
import androidx.viewbinding.ViewBinding
import com.alibaba.android.arouter.launcher.ARouter
import com.quyunshuo.base.utils.BindingReflex
import com.quyunshuo.base.utils.EventBusRegister
import com.quyunshuo.base.utils.EventBusUtils
import com.quyunshuo.androidbaseframemvvm.base.utils.BindingReflex
import com.quyunshuo.androidbaseframemvvm.base.utils.EventBusRegister
import com.quyunshuo.androidbaseframemvvm.base.utils.EventBusUtils
/**
* @Author: QuYunShuo

View File

@ -1,4 +1,4 @@
package com.quyunshuo.base.mvvm.v
package com.quyunshuo.androidbaseframemvvm.base.mvvm.v
import android.os.Bundle
import android.view.LayoutInflater
@ -6,13 +6,11 @@ import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment
import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider
import androidx.viewbinding.ViewBinding
import com.alibaba.android.arouter.launcher.ARouter
import com.quyunshuo.base.utils.BindingReflex
import com.quyunshuo.base.utils.EventBusRegister
import com.quyunshuo.base.utils.EventBusUtils
import java.lang.reflect.ParameterizedType
import com.quyunshuo.androidbaseframemvvm.base.utils.BindingReflex
import com.quyunshuo.androidbaseframemvvm.base.utils.EventBusRegister
import com.quyunshuo.androidbaseframemvvm.base.utils.EventBusUtils
/**
* @Author: QuYunShuo

View File

@ -1,14 +1,12 @@
package com.quyunshuo.base.mvvm.v
package com.quyunshuo.androidbaseframemvvm.base.mvvm.v
import android.os.Bundle
import android.view.LayoutInflater
import androidx.appcompat.app.AppCompatActivity
import androidx.viewbinding.ViewBinding
import com.alibaba.android.arouter.launcher.ARouter
import com.quyunshuo.base.utils.BindingReflex
import com.quyunshuo.base.utils.EventBusRegister
import com.quyunshuo.base.utils.EventBusUtils
import java.lang.reflect.ParameterizedType
import com.quyunshuo.androidbaseframemvvm.base.utils.BindingReflex
import com.quyunshuo.androidbaseframemvvm.base.utils.EventBusRegister
import com.quyunshuo.androidbaseframemvvm.base.utils.EventBusUtils
/**
* @Author: QuYunShuo

View File

@ -1,4 +1,4 @@
package com.quyunshuo.base.mvvm.v
package com.quyunshuo.androidbaseframemvvm.base.mvvm.v
import android.os.Bundle
import android.view.LayoutInflater
@ -7,10 +7,9 @@ import android.view.ViewGroup
import androidx.fragment.app.Fragment
import androidx.viewbinding.ViewBinding
import com.alibaba.android.arouter.launcher.ARouter
import com.quyunshuo.base.utils.BindingReflex
import com.quyunshuo.base.utils.EventBusRegister
import com.quyunshuo.base.utils.EventBusUtils
import java.lang.reflect.ParameterizedType
import com.quyunshuo.androidbaseframemvvm.base.utils.BindingReflex
import com.quyunshuo.androidbaseframemvvm.base.utils.EventBusRegister
import com.quyunshuo.androidbaseframemvvm.base.utils.EventBusUtils
/**
* @Author: QuYunShuo

View File

@ -1,4 +1,4 @@
package com.quyunshuo.base.mvvm.v
package com.quyunshuo.androidbaseframemvvm.base.mvvm.v
import androidx.viewbinding.ViewBinding

View File

@ -1,4 +1,4 @@
package com.quyunshuo.base.mvvm.v
package com.quyunshuo.androidbaseframemvvm.base.mvvm.v
import androidx.viewbinding.ViewBinding

View File

@ -1,8 +1,8 @@
package com.quyunshuo.base.mvvm.vm
package com.quyunshuo.androidbaseframemvvm.base.mvvm.vm
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import com.quyunshuo.base.mvvm.m.BaseRepository
import com.quyunshuo.androidbaseframemvvm.base.mvvm.m.BaseRepository
/**
* @Author: QuYunShuo

View File

@ -1,4 +1,4 @@
package com.quyunshuo.base.utils
package com.quyunshuo.androidbaseframemvvm.base.utils
import android.app.Activity
import java.util.*

View File

@ -1,10 +1,10 @@
package com.quyunshuo.base.utils
package com.quyunshuo.androidbaseframemvvm.base.utils
import android.app.Activity
import android.content.Context
import android.view.View
import android.view.inputmethod.InputMethodManager
import com.quyunshuo.base.BaseApplication
import com.quyunshuo.androidbaseframemvvm.base.app.BaseApplication
import java.lang.reflect.Field
/**

View File

@ -1,4 +1,4 @@
package com.quyunshuo.base.utils
package com.quyunshuo.androidbaseframemvvm.base.utils
import android.view.LayoutInflater
import android.view.ViewGroup

View File

@ -1,4 +1,4 @@
package com.quyunshuo.base.utils
package com.quyunshuo.androidbaseframemvvm.base.utils
import java.text.ParseException
import java.text.SimpleDateFormat

View File

@ -1,4 +1,4 @@
package com.quyunshuo.base.utils
package com.quyunshuo.androidbaseframemvvm.base.utils
/**
* @Author: QuYunShuo

View File

@ -1,4 +1,4 @@
package com.quyunshuo.base.utils
package com.quyunshuo.androidbaseframemvvm.base.utils
import org.greenrobot.eventbus.EventBus

View File

@ -1,4 +1,4 @@
package com.quyunshuo.base.utils
package com.quyunshuo.androidbaseframemvvm.base.utils
import android.app.ActivityManager
import android.content.Context

View File

@ -1,4 +1,4 @@
package com.quyunshuo.base.utils
package com.quyunshuo.androidbaseframemvvm.base.utils
import android.content.Context
import com.tencent.mmkv.MMKV

View File

@ -1,5 +1,4 @@
package com.quyunshuo.base.utils;
package com.quyunshuo.androidbaseframemvvm.base.utils;
import android.content.Context;
import android.os.Build;
@ -12,7 +11,7 @@ import android.widget.Toast;
import androidx.annotation.StringRes;
import com.quyunshuo.base.BaseApplication;
import com.quyunshuo.androidbaseframemvvm.base.app.BaseApplication;
import java.lang.reflect.Field;

View File

@ -1,14 +1,13 @@
package com.quyunshuo.base.utils
package com.quyunshuo.androidbaseframemvvm.base.utils
import android.annotation.SuppressLint
import android.content.Context
import android.net.ConnectivityManager
import android.net.NetworkInfo
import android.os.Build
import android.util.Log
import android.widget.Toast
import com.alibaba.android.arouter.launcher.ARouter
import com.quyunshuo.base.BaseApplication
import com.quyunshuo.androidbaseframemvvm.base.app.BaseApplication
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.catch

View File

@ -0,0 +1 @@
apply("../buildGradleScript/lib_common.gradle")

View File

@ -0,0 +1,34 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.quyunshuo.androidbaseframemvvm.common">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<application android:name="com.quyunshuo.androidbaseframemvvm.base.app.BaseApplication">
<!-- 屏幕适配基准DP -->
<meta-data
android:name="design_width_in_dp"
android:value="360" />
<meta-data
android:name="design_height_in_dp"
android:value="640" />
<!-- 腾讯TBS X5内核初始化 dex2oat优化方案 -->
<service
android:name="com.tencent.smtt.export.external.DexClassLoaderProviderService"
android:label="dexopt"
android:process=":dexopt" />
<!-- Android P 限制 -->
<uses-library
android:name="org.apache.http.legacy"
android:required="false" />
</application>
</manifest>

View File

@ -0,0 +1,141 @@
package com.quyunshuo.androidbaseframemvvm.common
import android.annotation.SuppressLint
import android.app.Application
import android.content.Context
import android.util.Log
import com.alibaba.android.arouter.launcher.ARouter
import com.google.auto.service.AutoService
import com.quyunshuo.androidbaseframemvvm.base.app.ApplicationLifecycle
import com.quyunshuo.androidbaseframemvvm.base.app.BaseApplication
import com.quyunshuo.androidbaseframemvvm.base.app.InitDepend
import com.quyunshuo.androidbaseframemvvm.base.constant.VersionStatus
import com.quyunshuo.androidbaseframemvvm.base.utils.ProcessUtils
import com.quyunshuo.androidbaseframemvvm.base.utils.SpUtils
import com.tencent.bugly.crashreport.CrashReport
import com.tencent.smtt.export.external.TbsCoreSettings
import com.tencent.smtt.sdk.QbSdk
import com.tencent.smtt.sdk.QbSdk.PreInitCallback
/**
* 项目相关的Application
*
* @author Qu Yunshuo
* @since 4/16/21 3:37 PM
*/
@AutoService(ApplicationLifecycle::class)
class CommonApplication : ApplicationLifecycle {
/**
* 项目当前的版本状态
*/
val versionStatus: String by lazy { BaseApplication.context.getString(R.string.VERSION_STATUS) }
companion object {
// 全局CommonApplication
@SuppressLint("StaticFieldLeak")
lateinit var mCommonApplication: CommonApplication
}
/**
* 同[Application.attachBaseContext]
* @param context Context
*/
override fun onAttachBaseContext(context: Context) {
mCommonApplication = this
}
/**
* 同[Application.onCreate]
* @param application Application
*/
override fun onCreate(application: Application) {}
/**
* 同[Application.onTerminate]
* @param application Application
*/
override fun onTerminate(application: Application) {}
override fun initByFrontDesk(): InitDepend {
val worker = mutableListOf<() -> String>()
val main = mutableListOf<() -> String>()
// 以下只需要在主进程当中初始化 按需要调整
if (ProcessUtils.isMainProcess(BaseApplication.context)) {
worker.add { initMMKV() }
worker.add { initARouter() }
}
worker.add { initTencentBugly() }
return InitDepend(main, worker)
}
/**
* 不需要立即初始化的放在这里进行后台初始化
*/
override fun initByBackstage() {
initX5WebViewCore()
}
/**
* 腾讯TBS WebView X5 内核初始化
*/
private fun initX5WebViewCore() {
// dex2oat优化方案
val map = HashMap<String, Any>()
map[TbsCoreSettings.TBS_SETTINGS_USE_SPEEDY_CLASSLOADER] = true
map[TbsCoreSettings.TBS_SETTINGS_USE_DEXLOADER_SERVICE] = true
QbSdk.initTbsSettings(map)
// 允许使用非wifi网络进行下载
QbSdk.setDownloadWithoutWifi(true)
// 初始化
QbSdk.initX5Environment(BaseApplication.context, object : PreInitCallback {
override fun onCoreInitFinished() {
Log.d("ApplicationInit", " TBS X5 init finished")
}
override fun onViewInitFinished(p0: Boolean) {
// 初始化完成的回调为true表示x5内核加载成功否则表示x5内核加载失败会自动切换到系统内核
Log.d("ApplicationInit", " TBS X5 init is $p0")
}
})
}
/**
* 腾讯 MMKV 初始化
*/
private fun initMMKV(): String {
val result = SpUtils.initMMKV(BaseApplication.context)
return "MMKV -->> $result"
}
/**
* 阿里路由 ARouter 初始化
*/
private fun initARouter(): String {
// 测试环境下打开ARouter的日志和调试模式 正式环境需要关闭
if (versionStatus == VersionStatus.ALPHA || versionStatus == VersionStatus.BETA) {
ARouter.openLog() // 打印日志
ARouter.openDebug() // 开启调试模式(如果在InstantRun模式下运行必须开启调试模式线上版本需要关闭,否则有安全风险)
}
ARouter.init(BaseApplication.application)
return "ARouter -->> init complete"
}
/**
* 初始化 腾讯Bugly
* 测试环境应该与正式环境的日志收集渠道分隔开
* 目前有两个渠道 测试版本/正式版本
*/
private fun initTencentBugly(): String {
// 第三个参数为SDK调试模式开关
CrashReport.initCrashReport(
BaseApplication.context,
BaseApplication.context.getString(R.string.BUGLY_APP_ID),
versionStatus == VersionStatus.ALPHA || versionStatus == VersionStatus.BETA
)
return "Bugly -->> init complete"
}
}

View File

@ -1,4 +1,4 @@
package com.quyunshuo.common.constant
package com.quyunshuo.androidbaseframemvvm.common.constant
/**
* @Author: QuYunShuo

View File

@ -1,4 +1,4 @@
package com.quyunshuo.common.constant
package com.quyunshuo.androidbaseframemvvm.common.constant
/**
* @Author: QuYunShuo

View File

@ -1,4 +1,4 @@
package com.quyunshuo.common.constant
package com.quyunshuo.androidbaseframemvvm.common.constant
/**
* @Author: QuYunShuo

View File

@ -1,8 +1,8 @@
package com.quyunshuo.common.ui
package com.quyunshuo.androidbaseframemvvm.common.ui
import androidx.lifecycle.ViewModel
import androidx.viewbinding.ViewBinding
import com.quyunshuo.base.mvvm.v.BaseFrameActivity
import com.quyunshuo.androidbaseframemvvm.base.mvvm.v.BaseFrameActivity
/**
* @Author: QuYunShuo

View File

@ -1,8 +1,8 @@
package com.quyunshuo.common.ui
package com.quyunshuo.androidbaseframemvvm.common.ui
import androidx.lifecycle.ViewModel
import androidx.viewbinding.ViewBinding
import com.quyunshuo.base.mvvm.v.BaseFrameFragment
import com.quyunshuo.androidbaseframemvvm.base.mvvm.v.BaseFrameFragment
/**
* @Author: QuYunShuo

View File

@ -1,7 +1,7 @@
package com.quyunshuo.common.ui
package com.quyunshuo.androidbaseframemvvm.common.ui
import androidx.viewbinding.ViewBinding
import com.quyunshuo.base.mvvm.v.BaseFrameNotMVVMActivity
import com.quyunshuo.androidbaseframemvvm.base.mvvm.v.BaseFrameNotMVVMActivity
/**
* @Author: QuYunShuo

View File

@ -1,7 +1,7 @@
package com.quyunshuo.common.ui
package com.quyunshuo.androidbaseframemvvm.common.ui
import androidx.viewbinding.ViewBinding
import com.quyunshuo.base.mvvm.v.BaseFrameNotMVVMFragment
import com.quyunshuo.androidbaseframemvvm.base.mvvm.v.BaseFrameNotMVVMFragment
/**
* @Author: QuYunShuo

1
lib_net/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
/build

1
lib_net/build.gradle.kts Normal file
View File

@ -0,0 +1 @@
apply("../buildGradleScript/lib_net.gradle")

View File

21
lib_net/proguard-rules.pro vendored Normal file
View File

@ -0,0 +1,21 @@
# Add project specific ProGuard rules here.
# You can control the set of applied configuration files using the
# proguardFiles setting in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}
# Uncomment this to preserve the line number information for
# debugging stack traces.
#-keepattributes SourceFile,LineNumberTable
# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile

View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.quyunshuo.androidbaseframemvvm.net">
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
</manifest>

View File

@ -0,0 +1,47 @@
package com.quyunshuo.androidbaseframemvvm.net
import android.app.Application
import android.content.Context
import com.google.auto.service.AutoService
import com.quyunshuo.androidbaseframemvvm.base.app.ApplicationLifecycle
import com.quyunshuo.androidbaseframemvvm.base.app.InitDepend
/**
* 网络模块的Application
*
* @author Qu Yunshuo
* @since 4/23/21 6:14 PM
*/
@AutoService(ApplicationLifecycle::class)
class NetApplication : ApplicationLifecycle {
/**
* 同[Application.attachBaseContext]
* @param context Context
*/
override fun onAttachBaseContext(context: Context) {}
/**
* 同[Application.onCreate]
* @param application Application
*/
override fun onCreate(application: Application) {}
/**
* 同[Application.onTerminate]
* @param application Application
*/
override fun onTerminate(application: Application) {}
/**
* 需要立即进行初始化的放在这里进行并行初始化
* 需要必须在主线程初始化的放在[InitDepend.mainThreadDepends],反之放在[InitDepend.workerThreadDepends]
* @return InitDepend 初始化方法集合
*/
override fun initByFrontDesk(): InitDepend = InitDepend(mutableListOf(), mutableListOf())
/**
* 不需要立即初始化的放在这里进行后台初始化
*/
override fun initByBackstage() {}
}

View File

@ -0,0 +1,12 @@
package com.quyunshuo.androidbaseframemvvm.net
/**
* 接口公共地址
*
* @author Qu Yunshuo
* @since 4/17/21 3:27 PM
*/
internal object NetBaseUrl {
const val BASE_URLl = ""
}

View File

@ -0,0 +1,62 @@
package com.quyunshuo.androidbaseframemvvm.net
import okhttp3.Interceptor
import okhttp3.OkHttpClient
import okhttp3.logging.HttpLoggingInterceptor
import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory
import java.util.concurrent.TimeUnit
/**
* 网络客户端提供者
*
* @author Qu Yunshuo
* @since 4/17/21 2:35 PM
*/
object NetClientProvider {
/**
* 连接超时
*/
private const val CONNECT_TIME_OUT = 15L * 1000L
/**
* 读取超时
*/
private const val READ_TIME_OUT = 20L * 1000L
/**
* 日志拦截器
*/
private val mLogInterceptor: Interceptor by lazy(mode = LazyThreadSafetyMode.SYNCHRONIZED) {
val level = if (BuildConfig.DEBUG) {
HttpLoggingInterceptor.Level.BODY
} else {
HttpLoggingInterceptor.Level.NONE
}
HttpLoggingInterceptor().setLevel(level)
}
/**
* OkHttpClient
*/
private val mOkHttpClient: OkHttpClient by lazy(mode = LazyThreadSafetyMode.SYNCHRONIZED) {
OkHttpClient.Builder()
.connectTimeout(CONNECT_TIME_OUT, TimeUnit.MILLISECONDS) // 连接超时
.readTimeout(READ_TIME_OUT, TimeUnit.MILLISECONDS) // 读取超时
.addInterceptor(mLogInterceptor) // 日志拦截器
.retryOnConnectionFailure(true) // 失败重连
.build()
}
/**
* 项目服务器Retrofit
*/
val mRetrofit: Retrofit by lazy(mode = LazyThreadSafetyMode.SYNCHRONIZED) {
Retrofit.Builder()
.baseUrl(NetBaseUrl.BASE_URLl)
.addConverterFactory(GsonConverterFactory.create()) // Gson转换器
.client(mOkHttpClient)
.build()
}
}

View File

@ -1,4 +0,0 @@
include ':Lib_Common'
include ':Lib_Base'
include ':app'
rootProject.name = "AndroidBaseFrameMVVM"

6
settings.gradle.kts Normal file
View File

@ -0,0 +1,6 @@
include(
":app",
":lib_base",
":lib_common",
":lib_net"
)