Browse Source

base

master
suliang 2 years ago
parent
commit
6cb51f74c1
32 changed files with 615 additions and 275 deletions
  1. 1
    0
      .idea/gradle.xml
  2. 2
    0
      .idea/misc.xml
  3. 4
    0
      ProjectErrors.md
  4. 2
    0
      README.md
  5. 55
    23
      app/build.gradle
  6. 6
    2
      app/src/main/AndroidManifest.xml
  7. 1
    1
      app/src/main/java/com/xkl/cdl/module/m_center_learn/LearnCenterFragment.kt
  8. 1
    1
      app/src/main/java/com/xkl/cdl/module/m_memo/MemoFragment.kt
  9. 1
    1
      app/src/main/java/com/xkl/cdl/module/m_my/MyFragment.kt
  10. 1
    1
      app/src/main/java/com/xkl/cdl/module/m_statics/StaticsFragment.kt
  11. 46
    0
      app/src/main/java/com/xkl/cdl/module/splash/SplashActivity.kt
  12. BIN
      app/src/main/res/drawable/illustration_splash.png
  13. 12
    0
      app/src/main/res/drawable/theme_splash_bg.xml
  14. 40
    0
      app/src/main/res/layout/activity_splash.xml
  15. 1
    1
      app/src/main/res/layout/fragment_learn_center.xml
  16. 1
    1
      app/src/main/res/layout/fragment_memo.xml
  17. 1
    1
      app/src/main/res/layout/fragment_my.xml
  18. 1
    1
      app/src/main/res/layout/fragment_statics.xml
  19. BIN
      app/src/main/res/mipmap-xxxhdpi/splash_logo.png
  20. 26
    10
      app/src/main/res/values/themes.xml
  21. 31
    8
      build.gradle
  22. 38
    5
      lib/common/build.gradle
  23. 52
    18
      lib/common/src/main/java/com/suliang/common/base/activity/BaseActivity.kt
  24. 25
    0
      lib/common/src/main/java/com/suliang/common/base/activity/BaseActivityVM.kt
  25. 129
    0
      lib/common/src/main/java/com/suliang/common/base/adapter/BaseAdapter.kt
  26. 6
    0
      lib/common/src/main/java/com/suliang/common/base/adapter/BaseAdapterViewHolder.kt
  27. 33
    1
      lib/common/src/main/java/com/suliang/common/base/fragment/BaseFragment.kt
  28. 17
    0
      lib/common/src/main/java/com/suliang/common/base/fragment/BaseFragmentVM.kt
  29. 36
    0
      lib/common/src/main/java/com/suliang/common/extension/BindingExtension.kt
  30. 44
    0
      lib/common/src/main/java/com/suliang/common/util/ActivityStackManager.kt
  31. 0
    200
      lib/common/src/main/java/com/suliang/common/util/Constants.kt
  32. 2
    0
      settings.gradle

+ 1
- 0
.idea/gradle.xml View File

<option name="testRunner" value="GRADLE" /> <option name="testRunner" value="GRADLE" />
<option name="distributionType" value="DEFAULT_WRAPPED" /> <option name="distributionType" value="DEFAULT_WRAPPED" />
<option name="externalProjectPath" value="$PROJECT_DIR$" /> <option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="gradleJvm" value="Embedded JDK" />
<option name="modules"> <option name="modules">
<set> <set>
<option value="$PROJECT_DIR$" /> <option value="$PROJECT_DIR$" />

+ 2
- 0
.idea/misc.xml View File

<component name="DesignSurface"> <component name="DesignSurface">
<option name="filePathToZoomLevelMap"> <option name="filePathToZoomLevelMap">
<map> <map>
<entry key="..\:/Work/XKL/XklLocal/app/src/main/res/drawable/theme_splash_bg.xml" value="0.22" />
<entry key="..\:/Work/XKL/XklLocal/app/src/main/res/layout/activity_fullscreen.xml" value="0.10144927536231885" /> <entry key="..\:/Work/XKL/XklLocal/app/src/main/res/layout/activity_fullscreen.xml" value="0.10144927536231885" />
<entry key="..\:/Work/XKL/XklLocal/app/src/main/res/layout/activity_main.xml" value="0.1" /> <entry key="..\:/Work/XKL/XklLocal/app/src/main/res/layout/activity_main.xml" value="0.1" />
<entry key="..\:/Work/XKL/XklLocal/app/src/main/res/layout/activity_splash.xml" value="0.1" />
</map> </map>
</option> </option>
</component> </component>

+ 4
- 0
ProjectErrors.md View File

项目中遇到的错误:
使用jectPack时的依赖:
· androidx.appcompat: appcompat 依赖中已经带了livedata、viewmodel等,可以不用再依赖,再依赖时出现了异常编译错误,未解决
且 依赖版本不同,对应的livedata等版本也不同

+ 2
- 0
README.md View File

ext.dependencies_androidTestImplementation : 测试依赖 ext.dependencies_androidTestImplementation : 测试依赖
ext.dependencies_custom : 自己添加的依赖项,按需定制 ext.dependencies_custom : 自己添加的依赖项,按需定制


androidx.appcompat:appcompat 自带jetpack中的lifecycle、viewmodel、livedata

app: app:
module : 按模块进行业务划分 module : 按模块进行业务划分



+ 55
- 23
app/build.gradle View File

plugins { plugins {
id 'com.android.application' id 'com.android.application'
id 'kotlin-android' id 'kotlin-android'
id 'kotlin-kapt'
} }
def androidConfig = rootProject.ext.android def androidConfig = rootProject.ext.android
android { android {


//配置产品变种 与 构建变体 //配置产品变种 与 构建变体
//flavorDimensions :变种维度 //flavorDimensions :变种维度
flavorDimensions "version"
productFlavors{ //产品变种
demo{
dimension "version"
//applicationId后追加 .demo 也可以重新定义applicationId 属性
applicationIdSuffix ".demo"
versionNameSuffix "-demo"
}
full {
dimension "version"
applicationIdSuffix ".full"
versionNameSuffix '-full'
}
}
// flavorDimensions "version"
// productFlavors{ //产品变种
// demo{
// dimension "version"
// //applicationId后追加 .demo 也可以重新定义applicationId 属性
// applicationIdSuffix ".demo"
// versionNameSuffix "-demo"
// }
// full {
// dimension "version"
// applicationIdSuffix ".full"
// versionNameSuffix '-full'
// }
// }
//变体过滤器 //变体过滤器
variantFilter { variant ->
def names = variant.flavors*.name
if (name.contains("demo")){
setIgnore(true)
}
}
// variantFilter { variant ->
// def names = variant.flavors*.name
// if (name.contains("demo")){
// setIgnore(true)
// }
// }


compileOptions { compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8 sourceCompatibility JavaVersion.VERSION_1_8
} }
buildFeatures { buildFeatures {
viewBinding true viewBinding true
dataBinding true
} }
} }


dependencies { dependencies {
implementation 'androidx.appcompat:appcompat:1.2.0'
implementation 'com.google.android.material:material:1.3.0'
implementation 'androidx.constraintlayout:constraintlayout:2.0.4'
implementation 'androidx.legacy:legacy-support-v4:1.0.0' implementation 'androidx.legacy:legacy-support-v4:1.0.0'
implementation project(path: ':lib:common')
rootProject.ext.dependencies_required.each{ k, v -> implementation v} rootProject.ext.dependencies_required.each{ k, v -> implementation v}
testImplementation rootProject.ext.dependencies_testImplementation.junit testImplementation rootProject.ext.dependencies_testImplementation.junit
rootProject.ext.dependencies_androidTestImplementation.each{ k,v -> androidTestImplementation v} rootProject.ext.dependencies_androidTestImplementation.each{ k,v -> androidTestImplementation v}
// kapt rootProject.ext.dependencies_kapt.lifecycle_compiler
def lifecycle_version = "2.5.0-alpha02"
def arch_version = "2.1.0"
//
// // ViewModel
// implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:$lifecycle_version"
// // ViewModel utilities for Compose
// implementation "androidx.lifecycle:lifecycle-viewmodel-compose:$lifecycle_version"
// // LiveData
// implementation "androidx.lifecycle:lifecycle-livedata-ktx:$lifecycle_version"
// // Lifecycles only (without ViewModel or LiveData)
// implementation "androidx.lifecycle:lifecycle-runtime-ktx:$lifecycle_version"
//
// // Saved state module for ViewModel
// implementation "androidx.lifecycle:lifecycle-viewmodel-savedstate:$lifecycle_version"
//
// // Annotation processor
//// kapt "androidx.lifecycle:lifecycle-compiler:$lifecycle_version"
// // alternately - if using Java8, use the following instead of lifecycle-compiler
// implementation "androidx.lifecycle:lifecycle-common-java8:$lifecycle_version"
// // optional - helpers for implementing LifecycleOwner in a Service
// implementation "androidx.lifecycle:lifecycle-service:$lifecycle_version"
//
// // optional - ProcessLifecycleOwner provides a lifecycle for the whole application process
// implementation "androidx.lifecycle:lifecycle-process:$lifecycle_version"
//
// // optional - ReactiveStreams support for LiveData
// implementation "androidx.lifecycle:lifecycle-reactivestreams-ktx:$lifecycle_version"
//
// // optional - Test helpers for LiveData
// testImplementation "androidx.arch.core:core-testing:$arch_version"

} }

+ 6
- 2
app/src/main/AndroidManifest.xml View File

android:supportsRtl="true" android:supportsRtl="true"
android:theme="@style/Theme.XklLocal"> android:theme="@style/Theme.XklLocal">
<activity <activity
android:name=".module.main.MainActivity"
android:name=".module.splash.SplashActivity"
android:configChanges="orientation|keyboardHidden|screenSize" android:configChanges="orientation|keyboardHidden|screenSize"
android:exported="true" >
android:exported="true"
android:theme="@style/Theme.Splash">
<intent-filter> <intent-filter>
<action android:name="android.intent.action.MAIN" /> <action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" /> <category android:name="android.intent.category.LAUNCHER" />
</intent-filter> </intent-filter>
</activity> </activity>
<activity
android:name=".module.main.MainActivity"
android:configChanges="orientation|keyboardHidden|screenSize"/>
</application> </application>


</manifest> </manifest>

app/src/main/java/com/xkl/cdl/module/center_learn/LearnCenterFragment.kt → app/src/main/java/com/xkl/cdl/module/m_center_learn/LearnCenterFragment.kt View File

package com.xkl.cdl.module.center_learn
package com.xkl.cdl.module.m_center_learn


import android.os.Bundle import android.os.Bundle
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment

app/src/main/java/com/xkl/cdl/module/memo/MemoFragment.kt → app/src/main/java/com/xkl/cdl/module/m_memo/MemoFragment.kt View File

package com.xkl.cdl.module.memo
package com.xkl.cdl.module.m_memo


import android.os.Bundle import android.os.Bundle
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment

app/src/main/java/com/xkl/cdl/module/my/MyFragment.kt → app/src/main/java/com/xkl/cdl/module/m_my/MyFragment.kt View File

package com.xkl.cdl.module.my
package com.xkl.cdl.module.m_my


import android.os.Bundle import android.os.Bundle
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment

app/src/main/java/com/xkl/cdl/module/statics/StaticsFragment.kt → app/src/main/java/com/xkl/cdl/module/m_statics/StaticsFragment.kt View File

package com.xkl.cdl.module.statics
package com.xkl.cdl.module.m_statics


import android.os.Bundle import android.os.Bundle
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment

+ 46
- 0
app/src/main/java/com/xkl/cdl/module/splash/SplashActivity.kt View File

package com.xkl.cdl.module.splash

import android.os.Bundle
import android.os.Handler
import android.os.Looper
import android.os.Message
import androidx.databinding.ObservableField
import com.suliang.common.base.activity.BaseActivity
import com.xkl.cdl.databinding.ActivitySplashBinding

class SplashActivity : BaseActivity<ActivitySplashBinding>() {

val textvalue = ObservableField<String>()

private val handler = object : Handler(Looper.getMainLooper()){
override fun handleMessage(msg: Message) {
super.handleMessage(msg)
binding.text.text = textvalue.get()
}
}

override fun onCreate(savedInstanceState: Bundle?) {
if(!isTaskRoot){
finish()
return
}
super.onCreate(savedInstanceState)
}
var count = 1

override fun initActivity(savedInstanceState: Bundle?) {

val x = Tvalue(textvalue)
binding.name = x

handler.postDelayed(object : Runnable{
override fun run() {
count ++
textvalue.set("$count")
handler.postDelayed(this,1000)
}
},1000)

}
}
data class Tvalue(val value : ObservableField<String>)

BIN
app/src/main/res/drawable/illustration_splash.png View File


+ 12
- 0
app/src/main/res/drawable/theme_splash_bg.xml View File

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">

<item android:drawable="@color/white"/>

<item android:gravity="center" android:bottom="100dp">
<bitmap
android:src="@mipmap/splash_logo"
android:scaleType="centerInside"/>
</item>

</layer-list>

+ 40
- 0
app/src/main/res/layout/activity_splash.xml View File

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools">

<data>
<variable
name="name"
type="com.xkl.cdl.module.splash.Tvalue" />
</data>

<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".module.splash.SplashActivity">

<ImageView
android:id="@+id/img"
android:layout_width="match_parent"
android:layout_height="0dp"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintVertical_bias="0.6"
app:layout_constraintDimensionRatio="1125:813"
android:src="@drawable/illustration_splash"
/>
<TextView
android:id="@+id/text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@={name.value}"
android:textSize="18dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"/>

</androidx.constraintlayout.widget.ConstraintLayout>
</layout>

+ 1
- 1
app/src/main/res/layout/fragment_learn_center.xml View File

xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
tools:context=".module.center_learn.LearnCenterFragment">
tools:context=".module.m_center_learn.LearnCenterFragment">


<!-- TODO: Update blank fragment layout --> <!-- TODO: Update blank fragment layout -->
<TextView <TextView

+ 1
- 1
app/src/main/res/layout/fragment_memo.xml View File

xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
tools:context=".module.memo.MemoFragment">
tools:context=".module.m_memo.MemoFragment">


<!-- TODO: Update blank fragment layout --> <!-- TODO: Update blank fragment layout -->
<TextView <TextView

+ 1
- 1
app/src/main/res/layout/fragment_my.xml View File

xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
tools:context=".module.my.MyFragment">
tools:context=".module.m_my.MyFragment">


<!-- TODO: Update blank fragment layout --> <!-- TODO: Update blank fragment layout -->
<TextView <TextView

+ 1
- 1
app/src/main/res/layout/fragment_statics.xml View File

xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
tools:context=".module.statics.StaticsFragment">
tools:context=".module.m_statics.StaticsFragment">


<!-- TODO: Update blank fragment layout --> <!-- TODO: Update blank fragment layout -->
<TextView <TextView

BIN
app/src/main/res/mipmap-xxxhdpi/splash_logo.png View File


+ 26
- 10
app/src/main/res/values/themes.xml View File

<resources xmlns:tools="http://schemas.android.com/tools"> <resources xmlns:tools="http://schemas.android.com/tools">
<!-- Base application theme. --> <!-- Base application theme. -->
<style name="Theme.XklLocal" parent="Theme.MaterialComponents.DayNight.DarkActionBar">
<style name="Theme.XklLocal" parent="Theme.MaterialComponents.Light.DarkActionBar">
<!-- Primary brand color. --> <!-- Primary brand color. -->
<item name="colorPrimary">@color/purple_500</item>
<item name="colorPrimaryVariant">@color/purple_700</item>
<item name="colorOnPrimary">@color/white</item>
<!-- Secondary brand color. -->
<item name="colorSecondary">@color/teal_200</item>
<item name="colorSecondaryVariant">@color/teal_700</item>
<item name="colorOnSecondary">@color/black</item>
<!-- Status bar color. -->
<item name="android:statusBarColor" tools:targetApi="l">?attr/colorPrimaryVariant</item>
<item name="colorPrimary">@color/white</item> <!--AppBar背景色-->
<!-- <item name="colorPrimaryVariant">@color/white</item>-->
<item name="colorOnPrimary">@color/black</item>
<!-- &lt;!&ndash; Secondary brand color. &ndash;&gt;-->
<!-- <item name="colorSecondary">@color/white</item>-->
<!-- <item name="colorSecondaryVariant">@color/white</item>-->
<!-- <item name="colorOnSecondary">@color/white</item>-->
<!-- &lt;!&ndash; Status bar color. &ndash;&gt;-->
<item name="android:statusBarColor" tools:targetApi="l">@color/white</item>
<!-- Customize your theme here. --> <!-- Customize your theme here. -->
<item name="android:textAllCaps">false</item>
<item name="android:windowActionBar">false</item>
<item name="windowActionBar">false</item>
<item name="windowNoTitle">true</item>
<item name="android:windowNoTitle">true</item>
<item name="android:windowIsTranslucent">true</item>
<item name="android:windowDrawsSystemBarBackgrounds">true</item>
<item name="android:windowEnableSplitTouch">false</item>
<item name="android:splitMotionEvents">false</item>
<item name="android:windowBackground">@android:color/transparent</item>

</style>

<!--启动页背景图层-->
<style name="Theme.Splash" parent="Theme.XklLocal">
<item name="android:windowBackground">@drawable/theme_splash_bg</item>
</style> </style>


</resources> </resources>

+ 31
- 8
build.gradle View File

repositories { repositories {
google() google()
mavenCentral() mavenCentral()

maven { url 'https://jitpack.io' }
} }
dependencies { dependencies {
classpath "com.android.tools.build:gradle:7.0.1" classpath "com.android.tools.build:gradle:7.0.1"
//在项目级别定义某些属性并在所有模块之间共享这些属性 //在项目级别定义某些属性并在所有模块之间共享这些属性
ext { ext {
android = [ android = [
compile_sdk_version: 30, //使用rootProject.ext.android.compile_sdk_version
compile_sdk_version: 31, //使用rootProject.ext.android.compile_sdk_version
build_tools_version: "30.0.2", build_tools_version: "30.0.2",
min_sdk_version : 21, min_sdk_version : 21,
target_sdk_version : 30,
target_sdk_version : 31,
version_code : 100, version_code : 100,
version_name : "100", version_name : "100",
applicationId : "com.xkl.cdl" applicationId : "com.xkl.cdl"
] ]
versions = [ versions = [
core_ktx_version : "1.3.2", core_ktx_version : "1.3.2",
appcompat_version: "1.2.0",
appcompat_version: "1.4.1",
material_version : "1.3.0", material_version : "1.3.0",
lifecycle_version: "2.5.0-alpha02"
] ]
//必须依赖 //必须依赖
dependencies_required = [ dependencies_required = [
//为属于Android框架的通用库提供扩展程序 //为属于Android框架的通用库提供扩展程序
core_ktx : "androidx.core:core-ktx:${versions.core_ktx_version}",
core_ktx : "androidx.core:core-ktx:${versions.core_ktx_version}",
//Androidx 依赖 //Androidx 依赖
appcompat: "androidx.appcompat:appcompat:${versions.appcompat_version}",
appcompat : "androidx.appcompat:appcompat:${versions.appcompat_version}",
//material_design //material_design
material : "com.google.android.material:material:${versions.material_version}",
material : "com.google.android.material:material:${versions.material_version}",
//constraintlayout
constraintlayout : "androidx.constraintlayout:constraintlayout:2.0.4",
//lifecycle
// lifecycle : "androidx.lifecycle:lifecycle-runtime-ktx:${versions.lifecycle_version}",
// //lifecycle saved state module for viewmodel
//// lifecycle_viewmodel_savestate: "androidx.lifecycle:lifecycle-viewmodel-savedstate:${versions.lifecycle_version}",
// //ViewModel
// viewmodel : "androidx.lifecycle:lifecycle-viewmodel-ktx:${versions.lifecycle_version}",
// //livedata
// livedata : "androidx.lifecycle:lifecycle-livedata-ktx:${versions.lifecycle_version}",
//java8 lifecycle_compiler
// lifecycle_compiler : "androidx.lifecycle:lifecycle-common-java8:${versions.lifecycle_version}"
] ]
dependencies_testImplementation = [ dependencies_testImplementation = [
junit: "junit:junit:4.+" junit: "junit:junit:4.+"
test_ext_junit : "androidx.test.ext:junit:1.1.2", test_ext_junit : "androidx.test.ext:junit:1.1.2",
test_espresson_core: "androidx.test.espresso:espresso-core:3.3.0" test_espresson_core: "androidx.test.espresso:espresso-core:3.3.0"
] ]
//按需依赖项
dependencies_custom = []
//依赖项
dependencies_custom = [
//设置状态栏和导航栏的框架 https://github.com/Zackratos/UltimateBarX
UltimateBarX: "com.gitee.zackratos:UltimateBarX:0.8.0",
]
//注解
// dependencies_kapt = [
// lifecycle_compiler: "androidx.lifecycle:lifecycle-compiler:${versions.lifecycle_version}",
//
// ]




} }

+ 38
- 5
lib/common/build.gradle View File

kotlinOptions { kotlinOptions {
jvmTarget = '1.8' jvmTarget = '1.8'
} }
viewBinding{
enabled true
}
dataBinding{
enabled true
buildFeatures {
viewBinding true
dataBinding true
} }
} }


rootProject.ext.dependencies_required.each{ k,v -> implementation v} rootProject.ext.dependencies_required.each{ k,v -> implementation v}
testImplementation rootProject.ext.dependencies_testImplementation.junit testImplementation rootProject.ext.dependencies_testImplementation.junit
rootProject.ext.dependencies_androidTestImplementation.each{ k,v -> androidTestImplementation v} rootProject.ext.dependencies_androidTestImplementation.each{ k,v -> androidTestImplementation v}
// api rootProject.ext.dependencies_custom.UltimateBarX

// kapt rootProject.ext.dependencies_kapt.lifecycle_compiler

def lifecycle_version = "2.5.0-alpha02"
def arch_version = "2.1.0"

// // ViewModel
// implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:$lifecycle_version"
// // ViewModel utilities for Compose
// implementation "androidx.lifecycle:lifecycle-viewmodel-compose:$lifecycle_version"
// // LiveData
// implementation "androidx.lifecycle:lifecycle-livedata-ktx:$lifecycle_version"
// // Lifecycles only (without ViewModel or LiveData)
// implementation "androidx.lifecycle:lifecycle-runtime-ktx:$lifecycle_version"
//
// // Saved state module for ViewModel
// implementation "androidx.lifecycle:lifecycle-viewmodel-savedstate:$lifecycle_version"
//
// // Annotation processor
//// kapt "androidx.lifecycle:lifecycle-compiler:$lifecycle_version"
// // alternately - if using Java8, use the following instead of lifecycle-compiler
// implementation "androidx.lifecycle:lifecycle-common-java8:$lifecycle_version"
// // optional - helpers for implementing LifecycleOwner in a Service
// implementation "androidx.lifecycle:lifecycle-service:$lifecycle_version"
//
// // optional - ProcessLifecycleOwner provides a lifecycle for the whole application process
// implementation "androidx.lifecycle:lifecycle-process:$lifecycle_version"
//
// // optional - ReactiveStreams support for LiveData
// implementation "androidx.lifecycle:lifecycle-reactivestreams-ktx:$lifecycle_version"
//
// // optional - Test helpers for LiveData
// testImplementation "androidx.arch.core:core-testing:$arch_version"

} }

+ 52
- 18
lib/common/src/main/java/com/suliang/common/base/activity/BaseActivity.kt View File

package com.suliang.common.base.activity package com.suliang.common.base.activity


import android.os.Bundle import android.os.Bundle
import android.view.LayoutInflater
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import androidx.databinding.DataBindingUtil
import androidx.databinding.ViewDataBinding
import androidx.databinding.ViewDataBindingKtx
import java.lang.reflect.Method
import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.ViewModelProviders
import androidx.viewbinding.ViewBinding
import com.suliang.common.extension.initBinding
import com.suliang.common.util.ActivityStackManager
import java.lang.reflect.ParameterizedType import java.lang.reflect.ParameterizedType


/** /**
* 基类Activity * 基类Activity
*/ */
abstract class BaseActivity<VB : ViewDataBinding> : AppCompatActivity() {
lateinit var databinding: VB
abstract class BaseActivity<VB : ViewBinding> : AppCompatActivity() {

lateinit var binding: VB


override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
addStackManager()
initFirst()
initActivity(savedInstanceState) }

protected open fun initFirst() {
setLayoutBefore() setLayoutBefore()
initBinding()
binding = initBinding(layoutInflater)
setContentView(binding.root)
initStatusBar()
setLayoutAfter() setLayoutAfter()
}


/**
* 状态栏初始化方法
*/
open fun initStatusBar() {
// statusBarOnly {
// fitWindow = true
// color = Color.WHITE
// light = true
// }
}


override fun onDestroy() {
super.onDestroy()
ActivityStackManager.removeActivity(this)
} }


private fun addStackManager() {
ActivityStackManager.addActivity(this)
}

/** 布局前操作 : 空实现 */ /** 布局前操作 : 空实现 */
public fun setLayoutBefore() {
public open fun setLayoutBefore() {


} }


/** /**
* 实例化 binding和 设置布局
* 布局后操作:空实现
*/ */
private fun initBinding() {
// https://www.jianshu.com/p/e3d2421a0277
// val genericSuperClass = this::class.java.genericSuperclass as ParameterizedType //超类
// val type = genericSuperClass.actualTypeArguments[0].javaClass
// val infate: Method = type.getDeclaredMethod("inflate")
public open fun setLayoutAfter() {


} }


/** /**
* 布局后操作:空实现
* onCreate中给与app中用户的具体实现
* @param savedInstanceState Bundle?
*/ */
public fun setLayoutAfter() {
abstract fun initActivity(savedInstanceState: Bundle?)


}
// @SuppressWarnings("unchecked")
// fun initBinding(inflater: LayoutInflater): VB {
// val vbClass =
// (javaClass.genericSuperclass as ParameterizedType).actualTypeArguments.filterIsInstance<Class<VB>>()
// val inflate = vbClass[0].getDeclaredMethod("inflate", LayoutInflater::class.java)
// return inflate.invoke(null, inflater) as VB
// }


public abstract fun layoutRes(): Int
} }

+ 25
- 0
lib/common/src/main/java/com/suliang/common/base/activity/BaseActivityVM.kt View File

package com.suliang.common.base.activity

import android.os.Bundle
import androidx.databinding.ViewDataBinding
import androidx.lifecycle.ViewModel
import androidx.viewbinding.ViewBinding

/**
* Activity DataBinding 与 ViewModel基类,封装DataBinding和ViewModel
* @property VB : ViewDataBinding
* @property VM: ViewModel
*/
abstract class BaseActivityVM<VB : ViewDataBinding, VM:ViewModel> : BaseActivity<VB>() {

private lateinit var vm : VM

override fun initFirst() {
vm = initViewModel()
super.initFirst()
binding.lifecycleOwner = this
}

abstract fun initViewModel() : VM

}

+ 129
- 0
lib/common/src/main/java/com/suliang/common/base/adapter/BaseAdapter.kt View File

package com.suliang.common.base.adapter

import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView

abstract class BaseAdapter<T> :
RecyclerView.Adapter<BaseAdapterViewHolder>() {

companion object{
val TYPE_EMPTY = -1
}

//数据源
private var mData: MutableList<T> = mutableListOf<T>()

/** 是否需要显示空布局 */
var needShowEmptyView = false

/**
* 当前位置是否需要显示空布局,主要是为0的时候,这个判断才会有效
* @param position Int
*/
private fun enableEmptyPosition(position:Int): Boolean{
return position == 0 && mData.isEmpty() && needShowEmptyView
}

override fun getItemCount(): Int {
return if (needShowEmptyView && mData.isEmpty()) 1 else mData.size
}

override fun getItemViewType(position: Int): Int {
if (enableEmptyPosition(position)){
return TYPE_EMPTY
}
return super.getItemViewType(position)
}

override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): BaseAdapterViewHolder {
return when(viewType){
TYPE_EMPTY -> coverEmptyViewHolder(parent)
else -> coverViewHolder(parent,viewType)
}
}

override fun onBindViewHolder(holder: BaseAdapterViewHolder, position: Int) {
if (enableEmptyPosition(position)){
onBindEmptyViewHolder(holder)
}else{
onBindVH(holder,position)
}
}

/** 创建空布局的ViewHolder 如果needShowEmpty = false 则可以不创建 */
abstract fun coverEmptyViewHolder(parent: ViewGroup): BaseAdapterViewHolder
/** 空布局的数据绑定 */
abstract fun onBindEmptyViewHolder(holder: BaseAdapterViewHolder)
/** 创建 正常item的 ViewHolder */
abstract fun coverViewHolder(parent: ViewGroup,viewType: Int): BaseAdapterViewHolder
/** 绑定 正常item 的数据 */
abstract fun onBindVH(holder: BaseAdapterViewHolder,position: Int)



/**
* 设置数据,并更新列表
* @param data List<T>?
*/
fun setData(data: MutableList<T>?) {
data?.let { it -> //不为空
mData = it
} ?: let { //为空
mData = mutableListOf()
}
notifyItemRangeChanged(0, mData.size)
}









/**
* 添加单条数据
* @param data T?
* @param position Int?
*/
fun addData(data: T?, position: Int?) {
data?.let {
val size = mData.size
val startPosition = position?.let { it ->
when {
it < 0 -> 0
it >= size -> size
else -> it
}
} ?: size
mData.add(startPosition,data)
notifyItemInserted(startPosition)
notifyItemRangeChanged(startPosition,mData.size + 1)
}
}

/**
* 添加数据集
* @param data List<T>? 数据集
* @param position Int? 添加到指定位置,可空
*/
fun addData(data: List<T>?, position: Int? = null) {
if (!data.isNullOrEmpty()) {
val size = mData.size
val startPosition = position?.let { it ->
when {
it < 0 -> 0
it >= size -> size
else -> it
}
} ?: size
mData.addAll(startPosition, data)
//通知有新的item插入进来了
notifyItemInserted(startPosition)
//范围性更新,直接调用onBindViewHolder
notifyItemRangeChanged(startPosition, mData.size + 1 )
}
}

}

+ 6
- 0
lib/common/src/main/java/com/suliang/common/base/adapter/BaseAdapterViewHolder.kt View File

package com.suliang.common.base.adapter

import androidx.databinding.ViewDataBinding
import androidx.recyclerview.widget.RecyclerView

class BaseAdapterViewHolder(binding: ViewDataBinding) : RecyclerView.ViewHolder(binding.root)

+ 33
- 1
lib/common/src/main/java/com/suliang/common/base/fragment/BaseFragment.kt View File

package com.suliang.common.base.fragment package com.suliang.common.base.fragment


class BaseFragment {
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.databinding.ViewDataBinding
import androidx.fragment.app.Fragment
import com.suliang.common.extension.initBinding
/**
* Fragment ViewBinding基类,封装ViewDataBinding
* @property VB : ViewDataBinding
* @property VM: ViewModel
*/
abstract class BaseFragment<VB: ViewDataBinding>: Fragment(){
lateinit var binding: VB

override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
binding = initBinding(inflater,container)
return super.onCreateView(inflater, container, savedInstanceState)
}

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
initFirst()
initFragment()
}

abstract fun initFirst()
abstract fun initFragment()

} }

+ 17
- 0
lib/common/src/main/java/com/suliang/common/base/fragment/BaseFragmentVM.kt View File

package com.suliang.common.base.fragment

import androidx.databinding.ViewDataBinding
import androidx.lifecycle.ViewModel
/**
* Fragment DataBinding 与 ViewModel基类,封装DataBinding和ViewModel
* @property VB : ViewDataBinding
* @property VM: ViewModel
*/
abstract class BaseFragmentVM<VB:ViewDataBinding,VM:ViewModel>:BaseFragment<VB>() {
lateinit var viewModel: VM
override fun initFirst() {
viewModel = initViewModel()
}

abstract fun initViewModel():VM
}

+ 36
- 0
lib/common/src/main/java/com/suliang/common/extension/BindingExtension.kt View File

package com.suliang.common.extension

import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.viewbinding.ViewBinding
import java.lang.reflect.ParameterizedType

/**
* 扩展方法,获取到ViewBinding的子类VB实例,主要用于Activity
* @receiver VB
* @param inflater LayoutInflater
* @param vbPosition Int 在超类泛型中的vb位置
* @return VB
*/
@SuppressWarnings("unchecked")
inline fun <VB : ViewBinding> Any.initBinding(inflater: LayoutInflater,vbPosition:Int = 0): VB {
val vbClass =
(javaClass.genericSuperclass as ParameterizedType).actualTypeArguments.filterIsInstance<Class<VB>>()
val inflate = vbClass[vbPosition].getDeclaredMethod("inflate", LayoutInflater::class.java)
return inflate.invoke(null, inflater) as VB
}

/**
* 扩展方法,获取ViewBinding的实例 主要用于Fragment、ListItem等
* @receiver Any
* @param inflater LayoutInflater
* @param container ViewGroup?
* @param vbPosition Int
* @return VB
*/
@SuppressWarnings("unchecked")
inline fun <VB: ViewBinding> Any.initBinding(inflater: LayoutInflater, container:ViewGroup?,vbPosition:Int = 0):VB{
val vbClass = (javaClass.genericSuperclass as ParameterizedType).actualTypeArguments.filterIsInstance<Class<VB>>()
val inflater = vbClass[vbPosition].getDeclaredMethod("inflate",LayoutInflater::class.java,ViewGroup::class.java,Boolean::class.java)
return inflater.invoke(null,inflater,container,false) as VB
}

+ 44
- 0
lib/common/src/main/java/com/suliang/common/util/ActivityStackManager.kt View File

package com.suliang.common.util

import android.app.Activity
import java.util.*

/**
* Activity 栈管理
*/
object ActivityStackManager {

@Volatile
private var activityStack: Stack<Activity> = Stack()

/**
* 入栈
* @param activity Activity
*/
fun addActivity(activity: Activity) {
activityStack.add(activity)
}

/**
* 出栈
* @param activity Activity
*/
fun removeActivity(activity: Activity) {
activityStack.remove(activity)
}

/**
* 结束指定类名的Activity
* @param cls Class<*>
*/
fun finishActivity(cls: Class<*>) {
run {
activityStack.forEach { activity ->
if (activity.javaClass == cls) {
activity.finish()
return@run
}
}
}
}
}

+ 0
- 200
lib/common/src/main/java/com/suliang/common/util/Constants.kt View File

package com.suliang.common.util

import java.io.File

/**
* author suliang
* create 2020/12/11 9:43
* Describe: 常量类
*/
object Constants {
const val PLATFORM = "android" //平台
const val YOUTH_VERSION = 1 //青少版
const val CHILDREN_VERSION = 2 //幼儿版


// public static final String ENVIRONMENT_PRODUCTION = "production" ; //正式环境
// public static final String ENVIRONMENT_DEVELOPMENT = "development"; //开发环境
// public static final String ENVIRONMENT_TEST = "test"; //测试环境
const val ACCOUNT = "account"
const val USER_INFO = "userinfo"
const val TOKEN = "token"

/** 默认发音 */
const val DEFAULT_SOUND = "default_sound"

/** 更换fragment中的颜色 */
const val ACTION_NOTIFY_FRAGMENT_SKIN = "notify_skin"

//项目subjectId
const val SUBJECT_ENGLISH: Long = 3 //英语
const val SUBJECT_CHINESE: Long = 1 //语文

//课程类型的coursepack --> categoryId
const val CATEGORY_ENGLISH_WORD: Long = 1 //英语: 单词速记
const val CATEGORY_ENGLISH_SOUNDMARK: Long = 4 //英语: 音标
const val CATEGORY_ENGLISH_SPOKEN: Long = 13 //英语: 口语
const val CATEGORY_CHINESE_COMPOSITION: Long = 2 //语文: 作文
const val CATEGORY_CHINESE_LITERACY: Long = 3 //语文: 识字
const val CATEGORY_CHINESE_PINYIN: Long = 5 //语文: 拼音

//项目的课程类型: course --> typeId
const val COURSE_TYPE_DISCERN = 1 //认读、口语
const val COURSE_TYPE_VOICE = 2 //辨音
const val COURSE_TYPE_SPELL = 3 //拼写
const val COURSE_TYPE_POINTS = 4 //作文知识点
const val COURSE_TYPE_LITERACY = 5 //识字
const val COURSE_TYPE_SOUNDMARK = 6 //音标
const val COURSE_TYPE_PINYIN = 7 //拼音
const val COURSE_TYPE_SPOKEN = 8 //口语

//作文课时类型
const val COMPOSITION_TYPE_VIDEO = 1 //视频
const val COMPOSITION_TYPE_KNOWLEDGE = 2 //知识点学习
const val COMPOSITION_TYPE_EXAM = 3 //知识点测试
const val COMPOSITION_TYPE_READING = 4 //课堂练习
const val COMPOSITION_TYPE_TASK = 5 //课外练习

//口语课时类型
const val SPOKEN_LESSON_TYPE_WORD = 1 //口语词汇
const val SPOKEN_LESSON_TYPE_SENTENCE = 2 //口语句型
const val SPOKEN_LESSON_TYPE_DIALOGUE = 3 //口语对话

//课程包过期信息状态值
const val EXPIRY_NOMAL = 1 //正常态
const val EXPIRY_WILL_OVER = 2 //快过期 小于39天
const val EXPIRY_OVER = 3 //已过期

//课程包内容是否下载状态值
const val CONTENT_NOT_DOWN = 0 //未下载
const val CONTENT_DOWNING = 1 //下载中
const val CONTENT_NOMAL = 2 //正常态(已下载)
val FILE_ENGLISH = "english" + File.separator + "pack" //英语项目包
val FILE_CHINESE = "chinese" + File.separator + "pack" //作文项目包

//课程数据包解压后保存的名称
const val DBFILENAME = "course_data.db"
const val FILE_VOICE = "voice" //音频地址
const val VOICE_COMMON_KONGGE = "kongge.mp3"
const val VOICE_COMMON_MISTAKE = "mistake.mp3"
const val VOICE_COMMON_DI = "di.mp3" //叮咚
const val FILE_UPLOAD_FAIL = "error" //上传失败地址
const val FILE_IMG = "glide" //图片缓存地址

/********发音默认type */
const val SOUND_TYPE_US = 1 //美
const val SOUND_TYPE_UK = 2 //英
const val SOUND_TYPE_CN = 3 //中文
const val TEST_QUEST_TYPE_FIELD = 1 //测试题选项类型 :字段名
const val TEST_QUEST_TYPE_ID = 2 //测试题选项类型: 选项id

// 分组(1:普通测试(词汇测试,不做redis统计关联) 2:章节学前测试 3:章节学后测试 4:学前总测试 5:学后总测试 6:备忘录测试(不做redis统计关联);7:作文知识点测试,8:服务中心的课程测试)
const val TEST_TYPE_NORMAL = 1 //普通测试(词汇测试,不做redis统计关联)
const val TEST_TYPE_BEFORE = 2 //学前测试
const val TEST_TYPE_AFTER = 3 //学后测试
const val TEST_TYPE_BEFORE_TOTAL = 4 //学前总测试
const val TEST_TYPE_AFTER_TOTAL = 5 //学后总测试
const val TEST_TYPE_MEMO = 6 //备忘录测试
const val TEST_TYPE_COMPOSITION = 7 //作文知识点测试
const val TEST_TYPE_SERVICE_CENTER = 8 //服务中心的课程测试
const val TEST_DB_DATA_WORD = 1 // data_word
const val TEST_DB_DATA_EXAM = 2 // data_exam
const val TEST_CORRECT = 1 //答题正确
const val TEST_ERROR = -1 //答题错误
const val TEST_UNANSWER = 0 //答题未答
const val TEST_TO_NEXT_TIME_CORRECT = 500 //认读辨音 正确 0.5秒跳下一题
const val TEST_TO_NEXT_TIME_ERROR = 2000 //认读辨音 答错 2秒
const val TEST_TO_NEXT_TIME_UNANSWER = 2000 //认读辨音 未答 2秒
const val TEST_TO_NEXT_TIME_SPELL = 1500 //辨音错误到下一题需要1.5秒
const val TEST_WORD_COUNT_DOWN_TIME_DISCERN = 6000 //认读单个单词倒计时时间 6秒
const val TEST_WORD_COUNT_DOWN_TIME_SPELL_SINGLE = 1600 //拼写单个单词字母的倒计时时间
const val TEST_WORD_COUNT_DOWN_TOME_COMPOSITION = 15000 //作文测试倒计时时间
const val SCORE_1 = 80 //小于score_1 悲伤
const val SCORE_2 = 90 //大于等于score1 小于 score_2 加油
const val SCORE_SPOKEN_DIALOGUE_1 = 60 //口语对话练习课时后测试通过标准 80以上优秀,中间良好
const val TEST_COUNT_TOTAL = 25 //总测试 50题
const val TEST_COUNT_NORAM = 20 //章节测试 25题
const val TEST_COUNT_VOCABULARY = 100 //词汇量测试

//测试的题目类型
const val TEST_QUEST_TYPE_CHOICE = 1 //选择题
const val TEST_QUEST_TYPE_GAP_FILLING = 2 //填空题
const val TEST_QUEST_TYPE_JUDGE = 3 //判断题
const val TEST_QUEST_TYPE_SPOKEN_DIALOGUE = 4 //口语对话测试

//课时状态
const val LESSON_STATE_NORMAL = 0 //普通状态

// public static final int LESSON_STATE_SELECT = 1 ; //选中状态
const val LESSON_STATE_LOCKED = 1 //锁定状态

//答题左侧按钮状态
const val ANSWER = 0 //答案
const val CORRECT = 1 //正确
const val NEXT = 2 //下一条

//有效时间 : 18秒
const val VALID_TIME: Long = 18000

//最后一课时 虚拟下一课时标记(主要用于判断最后一课时学后测试是否有通过)
const val LAST_LESSON_NEXT_FLAG = "-1_-1"

//学习
const val LEARN_FLAG = 1

//复习
const val REVIEW_FLAG = 2

//拼写中
const val STATE_SPELLING = 1

//纠错中
const val STATE_MODIFYING = 2

//不可操作状态
const val STATE_UNENABLE = 3

//拼写结果: 全对
const val RESULT_ALL_RIGHT = 1

//拼写结果:错误;可容错
const val RESULT_ERROR_CAN_MODIFY = 2

//拼写结果: 错误,无容错
const val RESULT_ERROR = 3

//拼写修改完成
const val RESULT_MODIFY_OVER = 4

// 0: 自己按顺序加载状态页 1复习页 2学前总测页 3 目录页 4学后总测未测 5、学后总测未通过 6、学后总测已通过
const val PAGE_LOADING_NORAML = 0
const val PAGE_LOADING_REVIEW = 1
const val PAGE_LOADING_BEFORE = 2
const val PAGE_LOADING_CATALOG = 3
const val PAGE_LOADING_AFTER_NOT = 4
const val PAGE_LOADING_AFTER_NO_PASS = 5
const val PAGE_LOADING_AFTER_PASS = 6

//收藏类型
const val COMPOSITON_COLLECT_VIDEO_BLACK_BOOK = 1 //收藏类型:视频版本
const val COMPOSITON_COLLECT_READING = 2 //阅读材料

//模块联通通知类型
const val NOTIFY_ENGLISH_REVIEW = 1 //英语有复习
const val NOTIFY_ENGLISH_ERROR = 2 //英语学习有错误
const val NOTIFY_COMPOSITION_REVIEW = 3 //作文有复习
const val NOTIFY_COMPOSITION_ERROR = 4 //作文学习有错误
const val NOTIFY_LEARN_RECORD_CHANGE = 5 //学习记录有变化

//游戏
const val GAME_GAPFILLING = 1 //填空
const val GAME_CHOOSE = 2 //消消乐
const val GAME_TRANSLATE = 3 //翻译排序

//口语自动播放模式
const val SPOKEN_AUTO_PLAY_MODEL = 1 //自动播放模式
const val SPOKEN_AUTO_FLOWER_MODEL = 2 //跟读模式

//收藏本: 句子type 2
const val COLLECT_TYPE_SENTENCE: Long = 2
}

+ 2
- 0
settings.gradle View File

google() google()
mavenCentral() mavenCentral()
jcenter() // Warning: this repository is going to shut down soon jcenter() // Warning: this repository is going to shut down soon

maven { url 'https://jitpack.io' }
} }
} }
rootProject.name = "XklLocal" rootProject.name = "XklLocal"

Loading…
Cancel
Save