├── .gitignore ├── README.md ├── app ├── .gitignore ├── build.gradle.kts ├── key.jks ├── proguard-rules.pro └── src │ └── main │ ├── AndroidManifest.xml │ ├── assets │ └── therouter │ │ └── routeMap.json │ ├── java │ └── pan │ │ └── lib │ │ └── baseandroidframework │ │ ├── CustomApplication.kt │ │ └── ui │ │ ├── SplashActivity.kt │ │ └── main │ │ └── MainActivity.kt │ └── res │ ├── drawable-v24 │ └── ic_launcher_foreground.xml │ ├── drawable │ └── ic_launcher_background.xml │ ├── layout │ ├── activity_main.xml │ └── activity_splash.xml │ ├── mipmap-anydpi-v26 │ ├── ic_launcher.xml │ └── ic_launcher_round.xml │ ├── mipmap-hdpi │ ├── ic_launcher.png │ └── ic_launcher_round.png │ ├── mipmap-mdpi │ ├── ic_launcher.png │ └── ic_launcher_round.png │ ├── mipmap-xhdpi │ ├── ic_launcher.png │ └── ic_launcher_round.png │ ├── mipmap-xxhdpi │ ├── ic_launcher.png │ └── ic_launcher_round.png │ ├── mipmap-xxxhdpi │ ├── ic_launcher.png │ └── ic_launcher_round.png │ └── values │ ├── colors.xml │ ├── strings.xml │ └── styles.xml ├── architecture.png ├── build.gradle.kts ├── common_lib ├── .gitignore ├── build.gradle.kts ├── consumer-rules.pro ├── proguard-rules.pro └── src │ └── main │ ├── AndroidManifest.xml │ ├── java │ └── pan │ │ └── lib │ │ └── common_lib │ │ ├── base │ │ ├── BaseActivity.kt │ │ ├── BaseApplication.kt │ │ ├── BaseDialogFragment.kt │ │ └── BaseRepository.kt │ │ ├── data │ │ └── User.kt │ │ ├── retrofit │ │ ├── ExceptionHandle.kt │ │ ├── NetResult.kt │ │ ├── Response.kt │ │ ├── ResultException.kt │ │ └── RetrofitManager.kt │ │ ├── utils │ │ ├── BitmapUtil.kt │ │ ├── DESUtil.java │ │ ├── LogUtil.kt │ │ ├── PreferencesUtil.kt │ │ ├── UserHelper.kt │ │ ├── WindowUtil.java │ │ └── ext │ │ │ ├── DimensionExt.kt │ │ │ ├── EditTextExt.kt │ │ │ ├── JsonExt.kt │ │ │ └── ViewModelExt.kt │ │ ├── views │ │ └── BottomDecoration.kt │ │ └── websocket │ │ ├── BaseLifecycle.kt │ │ └── WSManager.kt │ └── res │ ├── anim │ ├── popup_in.xml │ └── popup_out.xml │ ├── layout │ └── activity_base.xml │ └── values │ ├── colors.xml │ ├── strings.xml │ └── styles.xml ├── demo ├── .gitignore ├── README.md ├── build.gradle.kts ├── consumer-rules.pro └── src │ └── main │ ├── AndroidManifest.xml │ ├── java │ └── com │ │ └── example │ │ └── demo │ │ ├── di │ │ └── WanNetModule.kt │ │ ├── mockwebserver │ │ └── MockWebSocket.kt │ │ ├── pojo │ │ ├── Article.kt │ │ ├── ArticlesData.kt │ │ ├── Data.kt │ │ ├── Protocol.kt │ │ ├── Result.java │ │ └── WanResponse.kt │ │ ├── repository │ │ └── ArticleRepository.kt │ │ ├── service │ │ ├── DemoWebsocketService.kt │ │ └── WanApiService.kt │ │ └── ui │ │ ├── top │ │ ├── TopArticleActivity.kt │ │ ├── TopArticleAdapter.kt │ │ └── TopArticleViewModel.kt │ │ └── websocket_demo │ │ ├── WebsocketDemoActivity.kt │ │ └── WebsocketDemoViewModel.kt │ └── res │ ├── layout │ ├── activity_top_article.xml │ ├── activity_websocket_demo.xml │ └── item_top_article.xml │ └── values │ └── strings.xml ├── gradle.properties ├── gradle ├── libs.versions.toml └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── jitpack.yml └── settings.gradle.kts /.gitignore: -------------------------------------------------------------------------------- 1 | # Built application files 2 | *.apk 3 | *.aar 4 | *.ap_ 5 | *.aab 6 | 7 | # Files for the ART/Dalvik VM 8 | *.dex 9 | 10 | # Java class files 11 | *.class 12 | 13 | # Generated files 14 | bin/ 15 | gen/ 16 | out/ 17 | # Uncomment the following line in case you need and you don't have the release build type files in your app 18 | # release/ 19 | 20 | # Gradle files 21 | .gradle/ 22 | build/ 23 | 24 | # Local configuration file (sdk path, etc) 25 | local.properties 26 | 27 | # Proguard folder generated by Eclipse 28 | proguard/ 29 | 30 | # Log Files 31 | *.log 32 | 33 | # Android Studio Navigation editor temp files 34 | .navigation/ 35 | 36 | # Android Studio captures folder 37 | captures/ 38 | 39 | # IntelliJ 40 | *.iml 41 | .idea/workspace.xml 42 | .idea/tasks.xml 43 | .idea/gradle.xml 44 | .idea/assetWizardSettings.xml 45 | .idea/dictionaries 46 | .idea/libraries 47 | # Android Studio 3 in .gitignore file. 48 | .idea/caches 49 | .idea/modules.xml 50 | # Comment next line if keeping position of elements in Navigation Editor is relevant for you 51 | .idea/navEditor.xml 52 | 53 | # Keystore files 54 | # Uncomment the following lines if you do not want to check your keystore files in. 55 | #*.jks 56 | #*.keystore 57 | 58 | # External native build folder generated in Android Studio 2.2 and later 59 | .externalNativeBuild 60 | .cxx/ 61 | 62 | # Google Services (e.g. APIs or Firebase) 63 | # google-services.json 64 | 65 | # Freeline 66 | freeline.py 67 | freeline/ 68 | freeline_project_description.json 69 | 70 | # fastlane 71 | fastlane/report.xml 72 | fastlane/Preview.html 73 | fastlane/screenshots 74 | fastlane/test_output 75 | fastlane/readme.md 76 | 77 | # Version control 78 | vcs.xml 79 | 80 | # lint 81 | lint/intermediates/ 82 | lint/generated/ 83 | lint/outputs/ 84 | lint/tmp/ 85 | # lint/reports/ 86 | /.idea/ 87 | /app/release/ 88 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

BaseAndroidFramework

2 |

3 | 一款基于google官方推荐架构体系封装和Jetpack的MVVM框架。致力于写出最精简,易读性又高的代码,又保证项目的健壮性。 4 | 项目正在搭建中,如果喜欢的话不妨点个star~ 5 |

6 | 7 | ## 主要技术栈 8 | - Kotlin+ Coroutines+KTX 9 | - JetPack 10 | - [Dagger-Hilt](https://developer.android.com/training/dependency-injection/hilt-android)-用于依赖注入(ViewModel,Repository,ApiService) 11 | - LiveData 12 | - Lifecycle 13 | - ViewModel 14 | 15 | - [TheRouter](https://github.com/HuolalaTech/hll-wp-therouter-android) -跨模块通信框架 16 | - [Retrofit2 & OkHttp4](https://github.com/square/retrofit) -Retrofit2.11.0搭配协程 17 | - [Scarlet & Rxjava](https://github.com/Tinder/Scarlet) -Retrofit风格的WebSocket client 18 | - [Logger](https://github.com/orhanobut/logger) - Simple, pretty and powerful logger for android 19 | 20 | - [Kotson](https://github.com/SalomonBrys/Kotson)- 更简易的Gson使用 val userInfo: User="user json".toObject() 21 | 22 | 23 |
24 | 25 | ## HTTP请求Example 26 | 27 | ```kotlin 28 | @AndroidEntryPoint //注解的入口 29 | class TopArticleActivity : BaseActivity() { 30 | private val topArticleViewModel: TopArticleViewModel by viewModels() 31 | override fun onCreate(savedInstanceState: Bundle?) { 32 | super.onCreate(savedInstanceState) 33 | setContentView(R.layout.activity_top_article) 34 | 35 | initView() 36 | 37 | topArticleViewModel.fetchTopArticle() 38 | 39 | 40 | } 41 | 42 | } 43 | ``` 44 | 45 | #### @ViewModelInject依赖注入声明,会自动生成TopArticleViewModel_AssistedFactory,注入ArticleRepository 46 | ```kotlin 47 | class TopArticleViewModel @ViewModelInject constructor(private val articleRepository: ArticleRepository) : 48 | ViewModel() { 49 | 50 | 51 | val articleList = MutableLiveData>() 52 | 53 | fun fetchTopArticle() { 54 | launchOnUI { 55 | val response = articleRepository.fetchTopArticle() 56 | 57 | response.whenSuccess { 58 | articleList.value = it.toMutableList() 59 | } 60 | 61 | } 62 | } 63 | 64 | } 65 | ``` 66 | 67 | ```kotlin 68 | @Singleton 69 | class ArticleRepository @Inject constructor(private val wanApiService: WanApiService) : 70 | BaseRepository() { 71 | suspend fun fetchTopArticle(): NetResult> { 72 | return fetchApi { wanApiService.topArticle() } 73 | } 74 | 75 | } 76 | ``` 77 | 78 | ```kotlin 79 | @InstallIn(SingletonComponent::class) 80 | @Module 81 | object WanNetModule { 82 | @Provides 83 | @Singleton 84 | fun provideService(): WanApiService = RetrofitManager.getApiService( 85 | WanApiService::class.java) //提供WanApiService单例,只需要写一次 86 | 87 | } 88 | ``` 89 | 90 |
91 | 92 | ## WebSocket请求Example 93 | 94 | #### 声明接口 95 | ```kotlin 96 | interface DemoWebsocketService { 97 | @Send 98 | fun send(protocol: Protocol) 99 | 100 | @Receive 101 | fun observeCustomInfo(): Flowable 102 | 103 | @Receive 104 | fun observeWebSocketEvent(): Flowable 105 | 106 | @Send 107 | fun send(msg: String) 108 | } 109 | ``` 110 | 111 | #### 初始化WSManager 112 | ```kotlin 113 | val wsManager: WSManager = WSManager() 114 | ``` 115 | 116 | #### 发送消息 117 | ```kotlin 118 | wsManager.service.send(message) 119 | ``` 120 | 121 | #### 接收消息 122 | ```kotlin 123 | wsManager.service.observeCustomInfo().subscribe { 124 | receivedMessages.postValue(it.message) 125 | } 126 | ``` 127 | ## 架构图 128 | ![](architecture.png) -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /app/build.gradle.kts: -------------------------------------------------------------------------------- 1 | plugins { 2 | alias(libs.plugins.androidApplication) 3 | alias(libs.plugins.kotlinAndroid) 4 | alias(libs.plugins.kotlinKsp) 5 | alias(libs.plugins.daggerHiltAndroidPlugin) 6 | id ("therouter") 7 | } 8 | android { 9 | namespace = "pan.lib.baseandroidframework" 10 | 11 | compileSdk = libs.versions.compileSdkVersion.get().toInt() 12 | 13 | defaultConfig { 14 | applicationId = "pan.lib.baseandroidframework" 15 | minSdk = libs.versions.minSdk.get().toInt() 16 | targetSdk = libs.versions.targetSdk.get().toInt() 17 | versionCode = 1 18 | versionName = "1.0" 19 | ndk { 20 | abiFilters.add("arm64-v8a") 21 | } 22 | 23 | } 24 | 25 | signingConfigs { 26 | create("jks") { 27 | storeFile = file("key.jks") 28 | storePassword = "yesterday you said tomorrow" 29 | keyAlias = "key" 30 | keyPassword = "yesterday you said tomorrow" 31 | } 32 | } 33 | buildFeatures { 34 | viewBinding = true 35 | } 36 | buildTypes { 37 | release { 38 | signingConfig = signingConfigs.getByName("jks") 39 | isMinifyEnabled = true 40 | isShrinkResources = true 41 | proguardFiles( 42 | getDefaultProguardFile("proguard-android-optimize.txt"), 43 | "proguard-rules.pro" 44 | ) 45 | } 46 | debug { 47 | signingConfig = signingConfigs.getByName("jks") 48 | isMinifyEnabled = false 49 | } 50 | } 51 | compileOptions { 52 | sourceCompatibility = JavaVersion.VERSION_17 53 | targetCompatibility = JavaVersion.VERSION_17 54 | } 55 | 56 | kotlinOptions { 57 | jvmTarget = "17" 58 | } 59 | 60 | hilt { 61 | enableAggregatingTask = false 62 | } 63 | } 64 | 65 | dependencies { 66 | implementation(fileTree(mapOf("dir" to "libs", "include" to listOf("*.jar")))) 67 | implementation(project(":demo")) 68 | 69 | implementation(project(":common_lib")) 70 | // implementation(libs.baseAndroidFramework) 71 | implementation(libs.hilt.android) 72 | ksp(libs.hilt.compiler) 73 | ksp (libs.therouter.apt) 74 | } 75 | -------------------------------------------------------------------------------- /app/key.jks: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PanPersonalProject/BaseAndroidFramework/938d17f4553576b827c844dacf6d7f9cbee88a07/app/key.jks -------------------------------------------------------------------------------- /app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class name to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file name. 21 | #-renamesourcefileattribute SourceFile 22 | -keep public class com.alibaba.android.arouter.routes.**{*;} 23 | -keep public class com.alibaba.android.arouter.facade.**{*;} 24 | -keep class * implements com.alibaba.android.arouter.facade.template.ISyringe{*;} 25 | 26 | # If you use the byType method to obtain Service, add the following rules to protect the interface: 27 | -keep interface * implements com.alibaba.android.arouter.facade.template.IProvider 28 | 29 | # If single-type injection is used, that is, no interface is defined to implement IProvider, the following rules need to be added to protect the implementation 30 | -keep class * implements com.alibaba.android.arouter.facade.template.IProvider 31 | -dontwarn javax.lang.model.element.** 32 | -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 7 | 9 | 10 | 11 | 21 | 22 | 23 | 26 | 27 | 30 | 31 | 32 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /app/src/main/assets/therouter/routeMap.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "path": "/demo/WebsocketDemoActivity", 4 | "className": "com.example.demo.ui.websocket_demo.WebsocketDemoActivity", 5 | "action": "", 6 | "description": "", 7 | "params": {} 8 | }, 9 | { 10 | "path": "/demo/TopArticleActivity", 11 | "className": "com.example.demo.ui.top.TopArticleActivity", 12 | "action": "", 13 | "description": "", 14 | "params": {} 15 | } 16 | ] -------------------------------------------------------------------------------- /app/src/main/java/pan/lib/baseandroidframework/CustomApplication.kt: -------------------------------------------------------------------------------- 1 | package pan.lib.baseandroidframework 2 | 3 | import dagger.hilt.android.HiltAndroidApp 4 | import pan.lib.common_lib.base.BaseApplication 5 | 6 | /** 7 | * 8 | * Author: pan qi 9 | * CreateDate: 2020/6/3 15:44 10 | */ 11 | @HiltAndroidApp 12 | class CustomApplication : BaseApplication() { 13 | 14 | override fun onCreate() { 15 | super.onCreate() 16 | } 17 | } -------------------------------------------------------------------------------- /app/src/main/java/pan/lib/baseandroidframework/ui/SplashActivity.kt: -------------------------------------------------------------------------------- 1 | package pan.lib.baseandroidframework.ui 2 | 3 | import android.annotation.SuppressLint 4 | import android.content.Intent 5 | import android.os.Bundle 6 | import android.os.Handler 7 | import android.os.Looper 8 | import android.view.LayoutInflater 9 | import android.view.View 10 | import pan.lib.baseandroidframework.databinding.ActivitySplashBinding 11 | import pan.lib.baseandroidframework.ui.main.MainActivity 12 | import pan.lib.common_lib.base.BaseActivity 13 | import pan.lib.common_lib.utils.UserHelper 14 | 15 | @SuppressLint("CustomSplashScreen") 16 | class SplashActivity : BaseActivity() { 17 | private lateinit var binding: ActivitySplashBinding 18 | override fun onCreate(savedInstanceState: Bundle?) { 19 | super.onCreate(savedInstanceState) 20 | showToolbar(false) 21 | if (UserHelper.userInfo != null) { 22 | Handler(Looper.getMainLooper()).postDelayed({ 23 | startActivity(Intent(this, MainActivity::class.java)) 24 | finish() 25 | }, 2000) 26 | } else { 27 | startActivity(Intent(this, MainActivity::class.java)) 28 | finish() 29 | } 30 | 31 | 32 | } 33 | 34 | override fun getLayout(layoutInflater: LayoutInflater): View { 35 | binding = ActivitySplashBinding.inflate(layoutInflater) 36 | return binding.root 37 | } 38 | 39 | 40 | } 41 | -------------------------------------------------------------------------------- /app/src/main/java/pan/lib/baseandroidframework/ui/main/MainActivity.kt: -------------------------------------------------------------------------------- 1 | package pan.lib.baseandroidframework.ui.main 2 | 3 | import android.os.Bundle 4 | import android.view.LayoutInflater 5 | import android.view.View 6 | import com.therouter.TheRouter 7 | import pan.lib.baseandroidframework.databinding.ActivityMainBinding 8 | import pan.lib.common_lib.base.BaseActivity 9 | 10 | class MainActivity : BaseActivity() { 11 | 12 | private lateinit var binding: ActivityMainBinding 13 | override fun onCreate(savedInstanceState: Bundle?) { 14 | super.onCreate(savedInstanceState) 15 | 16 | setTitle("首页") 17 | binding.btRouter.setOnClickListener { 18 | TheRouter.build("/demo/TopArticleActivity") 19 | .navigation(this) 20 | } 21 | 22 | binding.btWebsocket.setOnClickListener { 23 | TheRouter.build("/demo/WebsocketDemoActivity") 24 | .navigation(this) 25 | } 26 | } 27 | 28 | 29 | override fun getLayout(layoutInflater: LayoutInflater): View { 30 | binding = ActivityMainBinding.inflate(layoutInflater) 31 | return binding.root 32 | } 33 | 34 | } 35 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-v24/ic_launcher_foreground.xml: -------------------------------------------------------------------------------- 1 | 7 | 8 | 9 | 15 | 18 | 21 | 22 | 23 | 24 | 30 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_launcher_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 10 | 15 | 20 | 25 | 30 | 35 | 40 | 45 | 50 | 55 | 60 | 65 | 70 | 75 | 80 | 85 | 90 | 95 | 100 | 105 | 110 | 115 | 120 | 125 | 130 | 135 | 140 | 145 | 150 | 155 | 160 | 165 | 170 | 171 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 11 |