├── .github
└── FUNDING.yml
├── .gitignore
├── .idea
├── .gitignore
└── copyright
│ ├── profiles_settings.xml
│ └── xuexiang.xml
├── LICENSE
├── README.md
├── app
├── .gitignore
├── build.gradle
├── channel
├── debug.jks
├── multiple-channel.gradle
├── proguard-rules.pro
├── src
│ ├── androidTest
│ │ └── java
│ │ │ └── com
│ │ │ └── xuexiang
│ │ │ └── kotlinsample
│ │ │ └── ExampleInstrumentedTest.kt
│ ├── main
│ │ ├── AndroidManifest.xml
│ │ ├── java
│ │ │ └── com
│ │ │ │ └── xuexiang
│ │ │ │ └── kotlinsample
│ │ │ │ ├── MyApp.kt
│ │ │ │ ├── activity
│ │ │ │ └── MainActivity.kt
│ │ │ │ ├── core
│ │ │ │ ├── BaseActivity.kt
│ │ │ │ ├── BaseContainerFragment.kt
│ │ │ │ ├── BaseFragment.kt
│ │ │ │ ├── BaseSimpleListFragment.kt
│ │ │ │ └── SimpleListAdapter.kt
│ │ │ │ ├── fragment
│ │ │ │ ├── CoroutinesFragment.kt
│ │ │ │ ├── KotlinBasicFragment.kt
│ │ │ │ ├── MainFragment.kt
│ │ │ │ ├── basic
│ │ │ │ │ ├── BitOperationFragment.kt
│ │ │ │ │ ├── LoopControlFragment.kt
│ │ │ │ │ ├── ReflectFragment.kt
│ │ │ │ │ ├── ScopeFunctionFragment.kt
│ │ │ │ │ ├── SimplifyUseFragment.kt
│ │ │ │ │ ├── VariableFragment.kt
│ │ │ │ │ ├── reflect
│ │ │ │ │ │ ├── GoodStudent.java
│ │ │ │ │ │ └── Student.java
│ │ │ │ │ └── simplify
│ │ │ │ │ │ ├── ArrayFragment.kt
│ │ │ │ │ │ ├── ConditionalFragment.kt
│ │ │ │ │ │ ├── Constructor.kt
│ │ │ │ │ │ ├── Extend.kt
│ │ │ │ │ │ ├── Extension.kt
│ │ │ │ │ │ ├── ExtensionFragment.kt
│ │ │ │ │ │ ├── Function.kt
│ │ │ │ │ │ ├── HighFunctionFragment.kt
│ │ │ │ │ │ ├── InterfaceSample.kt
│ │ │ │ │ │ └── StringFragment.kt
│ │ │ │ └── coroutines
│ │ │ │ │ ├── CoroutinesBasicFragment.kt
│ │ │ │ │ ├── CoroutinesFlowFragment.kt
│ │ │ │ │ ├── CoroutinesXTaskFragment.kt
│ │ │ │ │ ├── SchedulerChangeFragment.kt
│ │ │ │ │ ├── business
│ │ │ │ │ ├── ComplexBusinessFragment.kt
│ │ │ │ │ ├── entity
│ │ │ │ │ │ ├── Product.kt
│ │ │ │ │ │ ├── ProductFactory.kt
│ │ │ │ │ │ └── ProductInfo.kt
│ │ │ │ │ ├── processor
│ │ │ │ │ │ ├── AbstractProcessor.kt
│ │ │ │ │ │ ├── GetProductInfoProcessor.kt
│ │ │ │ │ │ ├── GivePriceProcessor.kt
│ │ │ │ │ │ ├── PublicProductProcessor.kt
│ │ │ │ │ │ └── SearchFactoryProcessor.kt
│ │ │ │ │ └── task
│ │ │ │ │ │ ├── AbstractTask.kt
│ │ │ │ │ │ ├── GetProductInfoTask.kt
│ │ │ │ │ │ ├── GivePriceTask.kt
│ │ │ │ │ │ ├── ProductTaskConstants.kt
│ │ │ │ │ │ ├── PublicProductTask.kt
│ │ │ │ │ │ └── SearchFactoryTask.kt
│ │ │ │ │ └── concurrent
│ │ │ │ │ ├── ConcurrentProcessFragment.kt
│ │ │ │ │ ├── entity
│ │ │ │ │ ├── BriefInfo.kt
│ │ │ │ │ ├── FactoryInfo.kt
│ │ │ │ │ ├── PriceInfo.kt
│ │ │ │ │ ├── Product.kt
│ │ │ │ │ ├── PromotionInfo.kt
│ │ │ │ │ └── RichInfo.kt
│ │ │ │ │ ├── processor
│ │ │ │ │ ├── GetBriefInfoProcessor.kt
│ │ │ │ │ ├── GetFactoryInfoProcessor.kt
│ │ │ │ │ ├── GetPriceInfoProcessor.kt
│ │ │ │ │ ├── GetPromotionInfoProcessor.kt
│ │ │ │ │ └── GetRichInfoProcessor.kt
│ │ │ │ │ └── task
│ │ │ │ │ ├── GetBriefInfoTask.kt
│ │ │ │ │ ├── GetFactoryInfoTask.kt
│ │ │ │ │ ├── GetPriceInfoTask.kt
│ │ │ │ │ ├── GetPromotionInfoTask.kt
│ │ │ │ │ └── GetRichInfoTask.kt
│ │ │ │ └── utils
│ │ │ │ ├── XToastUtils.kt
│ │ │ │ ├── sdkinit
│ │ │ │ ├── UMengInit.kt
│ │ │ │ └── XBasicLibInit.kt
│ │ │ │ └── service
│ │ │ │ └── JsonSerializationService.kt
│ │ └── res
│ │ │ ├── drawable-v24
│ │ │ └── ic_launcher_foreground.xml
│ │ │ ├── drawable
│ │ │ └── ic_launcher_background.xml
│ │ │ ├── layout
│ │ │ ├── adapter_item_simple_list_2.xml
│ │ │ └── fragment_usecase_compare.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
│ │ │ └── styles_widget.xml
│ └── test
│ │ └── java
│ │ └── com
│ │ └── xuexiang
│ │ └── kotlinsample
│ │ └── ExampleUnitTest.kt
└── x-library-simple.gradle
├── build.gradle
├── gradle.properties
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── settings.gradle
└── versions.gradle
/.github/FUNDING.yml:
--------------------------------------------------------------------------------
1 | # These are supported funding model platforms
2 |
3 | custom: https://gitee.com/xuexiangjys/Resource/blob/master/doc/sponsor.md
4 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | *.iml
2 | .gradle
3 | /LocalRepository
4 | /keystores
5 | /local.properties
6 | /.idea/caches
7 | /.idea/codeStyles
8 | /.idea/inspectionProfiles
9 | /.idea/libraries
10 | /.idea/dictionaries
11 | /.idea/markdown-navigator
12 | /.idea/*.xml
13 | .DS_Store
14 | /build
15 | /captures
16 | .externalNativeBuild
--------------------------------------------------------------------------------
/.idea/.gitignore:
--------------------------------------------------------------------------------
1 | # Default ignored files
2 | /shelf/
3 | /workspace.xml
4 |
--------------------------------------------------------------------------------
/.idea/copyright/profiles_settings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/.idea/copyright/xuexiang.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # KotlinSample
2 |
3 | Kotlin相关的案例
4 |
5 | ## 关于我
6 |
7 | | 公众号 | 掘金 | 知乎 | CSDN | 简书 | 思否 | 哔哩哔哩 | 今日头条
8 | |---------|---------|--------- |---------|---------|---------|---------|---------|
9 | | [我的Android开源之旅](https://t.1yb.co/Irse) | [点我](https://juejin.im/user/598feef55188257d592e56ed/posts) | [点我](https://www.zhihu.com/people/xuexiangjys/posts) | [点我](https://xuexiangjys.blog.csdn.net/) | [点我](https://www.jianshu.com/u/6bf605575337) | [点我](https://segmentfault.com/u/xuexiangjys) | [点我](https://space.bilibili.com/483850585) | [点我](https://img.rruu.net/image/5ff34ff7b02dd)
10 |
11 | ----
12 |
13 | ## Kotlin Coroutines
14 |
15 | * Coroutine:协程的概念和原理:协程是什么以及它的作用和特点,图解分析协程的工作原理。
16 | * Coroutine builders:协程的构建,协程构建器创建协程的三种方式。
17 | * CoroutineScope:协程作用域,协程运行的上下文环境,用来提供函数支持,也是用来增加限制。常见的7种作用域(包含Lifecycle支持的协程)以及作用域的分类和行为规则。
18 | * Job & Deferred:协程的句柄,实现对协程的控制和管理,Deferred有返回值。
19 | * CoroutineDispatcher:协程调度器,确定相应的协程在那个线程上执行,调度器的四种模式以及withContext主要是为了切换协程上下文环境。
20 | * CoroutineContext:协程上下文,表示协程的运行环境,包括协程调度器、代表协程本身的Job、协程名称、协程ID以及组合上下文的使用。
21 | * CoroutineStart:一个枚举类,为协程构建器定义四中启动模式。
22 | * suspend:挂起函数,Kotlin 协程最核心的关键字。一种避免阻塞线程并用更简单、更可控的操作替代线程阻塞的方法:协程挂起和恢复。
23 |
24 | ### 集成 Coroutines
25 |
26 | ```
27 | implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.0"
28 | implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.6.0"
29 | ```
30 |
31 | ### CoroutineContext
32 |
33 | > CoroutineContext即协程的上下文,是 Kotlin 协程的一个基本结构单元。巧妙的运用协程上下文是至关重要的,以此来实现正确的线程行为、生命周期、异常以及调试。它包含用户定义的一些数据集合,这些数据与协程密切相关。
34 |
35 | * Job: 控制协程的生命周期;
36 | * Deferred(async创建返回,可调用`await`获取返回结果)
37 | * SupervisorJob(特殊的 Job,里面的子Job不相互影响,一个子Job失败了,不影响其他子Job的执行)
38 | * CoroutineDispatcher: 向合适的线程分发任务;
39 | * Dispatchers.Default(一个CPU密集型任务调度器)
40 | * Dispatchers.IO(和Default共用一个共享的线程池)
41 | * Dispatchers.Unconfined(未定义线程池,默认在启动线程)
42 | * Dispatchers.Main(主线程,在Android上就是UI线程)
43 | * CoroutineName: 协程的名称,调试的时候很有用;
44 | * CoroutineExceptionHandler: 处理未被捕捉的异常。
45 |
46 | ### CoroutineStart
47 |
48 | > 协程启动模式
49 |
50 | * CoroutineStart.DEFAULT: 协程创建后立即开始调度(可能在执行前被取消)
51 | * CoroutineStart.ATOMIC: 协程创建后立即开始调度,协程执行到第一个挂起点之前不响应取消(将调度和执行两个步骤合二为一)
52 | * CoroutineStart.LAZY: 只要协程被需要时,包括主动调用该协程的start、join或者await等函数时才会开始调度
53 | * CoroutineStart.UNDISPATCHED: 立即执行协程体中的内容(没有调度的过程)
54 |
55 | ### CoroutineScope
56 |
57 | > 协程作用域。定义协程必须指定其 `CoroutineScope`。`CoroutineScope` 可被看作是一个具有超能力的 `ExecutorService` 的轻量级版本。`CoroutineScope` 会跟踪所有协程,同样它还可以取消由它所启动的所有协程。
58 |
59 | * GlobalScope - 全局作用域,不推荐使用
60 | * runBlocking{} - 主要用于测试
61 | * MainScope - 可用于开发(SupervisorJob() + Dispatchers.Main)
62 | * LifecycleOwner.lifecycleScope - 推荐使用
63 | * ViewModel.viewModelScope - 推荐使用
64 |
65 | ### coroutineScope & supervisorScope
66 |
67 | > 两个函数都是挂起函数,需要运行在协程内或挂起函数内。
68 |
69 | `coroutineScope`和`supervisorScope`都会返回一个作用域,它俩的差别就是异常传播。
70 |
71 | * `coroutineScope` 内部的异常会向上传播,子协程未捕获的异常会向上传递给父协程,任何一个子协程异常退出,会导致整体的退出;
72 | * `supervisorScope` 内部的异常不会向上传播,一个子协程异常退出,不会影响父协程和兄弟协程的运行。
73 |
74 | ----
75 |
76 | ## Kotlin语法
77 |
78 | ### let、with、run、apply、also等作用域函数
79 |
80 | 函数 | 函数块对象引用 | 返回值 | 是否拓展函数 | 使用场景
81 | |---|---|---|---|---
82 | let | it | Lambda表达式结果 | 是 | 1.适用于处理不为null的操作场景;2.明确一个变量所处的特定作用域范围内可使用。
83 | with| this | Lambda表达式结果 | 否(上下文对象作为参数) | 适用于同一个对象的公有属性和函数调用。
84 | run | this | Lambda表达式结果 | 是 | 适用于let函数和with函数的任何场景。对对象中的属性进行赋值和计算结果;在需要表达式的地方运行语句。
85 | apply | this | 返回this(对象本身) | 是 | 1.一般用于对象实例初始化的时候,需要对对象中的属性进行赋值;2.动态inflate一个View的时候需要给View绑定数据。
86 | also| it| 返回this(对象本身) | 是 | 适用于let函数的任何场景,对传入的对象进行操作,一般用于多个拓展函数的链式调用。
87 |
88 | * 1.`let`函数一般统一做空判断处理。
89 | * 2.`with`函数在同一个对象的多个方法时,可以省去类名重复。
90 | * 3.`run`函数适用于`let`函数和`with`函数的任何场景。`run`=`let`+`with`。
91 | * 4.`apply`函数整体上和`run`函数相似,唯一不同就是它的返回值是对象本身。
92 | * 5.`also`适用于`let`函数的任何场景,唯一不同就是它的返回值是对象本身。
93 |
94 | ### 变量基础
95 |
96 | * var:可变变量 var <表识符> : <类型>? = null/指定值
97 | * val:不可变变量 val <表识符> : <类型>? = null/指定值
98 | * `?`:表示该变量可为空
99 | * !!:不做空检查,判定一定非空,空的话会报错
100 | * lateinit: 修饰var变量,默认你会初始化,不做空检查
101 | * by lazy {}:修饰val变量,程序第一次使用到这个变量(或者对象)时再初始化
102 | * const:修饰val变量,代表常量
103 | * `data class`的copy()函数:进行对象的浅拷贝
104 | * `vararg`:代表可变数量的参数
105 | * `as`和`as?`:进行类型强转
106 |
107 | ### 位运算
108 |
109 | > Kotlin中的 位运算符 只对Int和Long两种 数据类型 起作用
110 |
111 | * 与: and(bits) == &
112 | * 或: or(bits) == |
113 | * 左移: shl(bits) == <<
114 | * 右移: shr(bits) == >>
115 |
116 | ### 数组和集合操作
117 |
118 | * 1.数组集合的创建
119 |
120 | ```kotlin
121 | // 数组
122 | val intArray = intArrayOf(1, 2, 3)
123 | // 集合
124 | val intList = listOf(1, 2, 3)
125 | val intSet = setOf(4, 5, 4, 6, 7, 5)
126 | // 可变集合
127 | val mutableList = mutableListOf(1, 2, 3)
128 | mutableList.add(4)
129 | val mutableMap = mutableMapOf(
130 | 1 to "1",
131 | 2 to "2",
132 | 3 to "3"
133 | )
134 | ```
135 |
136 | * 2.forEach:遍历
137 |
138 | ```kotlin
139 | intArrayOf(1, 2, 3).forEach { i ->
140 | Log.e(TAG, "遍历:$i")
141 | }
142 | ```
143 |
144 | * 3.filter:过滤
145 |
146 | ```kotlin
147 | // 遍历每个元素并按给的条件进行过滤,最终形成新的集合
148 | // 结果:[4, 8]
149 | intArrayOf(1, 2, 3, 4, 8).filter { i -> i > 3 }
150 | ```
151 |
152 | * 4.map:变换、
153 |
154 | ```kotlin
155 | // 遍历每个元素并执行给定表达式,最终形成新的集合
156 | // 结果:[3, 6, 9]
157 | intArrayOf(1, 2, 3).map { i -> i * 3 }
158 | ```
159 |
160 | * 5.flatMap:变换、创建、合并
161 |
162 | ```kotlin
163 | // 遍历每个元素,并为每个元素创建新的集合,最后合并到一个集合中
164 | // 结果:[3, 6, 9]
165 | intArrayOf(1, 2, 3).flatMap { i ->
166 | listOf("${i * 3}", "a") // 👈 生成新集合
167 | }
168 | ```
169 |
170 | * 6.find:寻找第一个符合要求的内容
171 |
172 | ```kotlin
173 | listOf(1, 2, 3, 4).find { it > 2 }
174 | ```
175 |
176 | * 7.any:判断是否存在符合要求的内容
177 |
178 | ```kotlin
179 | listOf(1, 2, 3, 4).any { it > 2 }
180 | ```
181 |
182 | * 8.count:获取符合要求内容的数量
183 |
184 | ```kotlin
185 | listOf(1, 2, 3, 4).count { it > 2 }
186 | ```
187 |
188 | * 9.maxBy:获取最大的内容
189 |
190 | ```kotlin
191 | listOf(1, 2, 3, 4).maxByOrNull { it }
192 | ```
193 |
194 | ### 反射使用
195 |
196 | * 1.反射设置/获取某个对象的成员属性:
197 |
198 | **xx.javaClass.getDeclaredField("xx")**
199 |
200 | ```kotlin
201 | student.javaClass.getDeclaredField("Name").run {
202 | isAccessible = true
203 | // 设置
204 | set(student, "xuexiang")
205 | // 获取
206 | get(student)
207 | }
208 | ```
209 |
210 | * 2.反射设置/获取某个对象的静态属性:
211 |
212 | **xx::class.java.getDeclaredField("xx")**
213 |
214 | ```kotlin
215 | Student::class.java.getDeclaredField("TotalNumber").run {
216 | isAccessible = true
217 | // 设置
218 | set(null, 1111)
219 | // 获取
220 | get(null)
221 | }
222 | ```
223 |
224 | * 3.反射执行某对象的成员方法:
225 |
226 | **xx.javaClass.getDeclaredMethod(xx, xx::class.java)**
227 |
228 | ```kotlin
229 | student.javaClass.getDeclaredMethod("getName", Integer::class.java).run {
230 | isAccessible = true
231 | Log.e(TAG, "invokeMethod: ${invoke(student, 23)}")
232 | }
233 | ```
234 |
235 | * 4.反射执行某个类的静态方法:
236 |
237 | **xx::class.java.getDeclaredMethod(xx, xx::class.java)**
238 |
239 | ```kotlin
240 | Student::class.java.getDeclaredMethod("incrementTotalNumber", Int::class.java).run {
241 | isAccessible = true
242 | Log.e(TAG, "invokeStaticMethod: ${invoke(null, 23)}")
243 | }
244 | ```
245 |
246 | * 5.反射构建实例:
247 |
248 | **xx::class.java.getDeclaredConstructor(xx::class.java...)**
249 |
250 | ```kotlin
251 | Student::class.java.getDeclaredConstructor(Int::class.java, String::class.java).run {
252 | isAccessible = true
253 | val std = newInstance(666, "xiaohuang")
254 | Log.e(TAG, "newInstance: $std")
255 |
256 | GoodStudent::class.java.getDeclaredConstructor(Student::class.java).run {
257 | isAccessible = true
258 | val goodStd = newInstance(std)
259 | Log.e(TAG, "GoodStudent: $goodStd")
260 | }
261 | }
262 | ```
263 |
264 | ----
265 |
266 |
267 | ## 相关文章
268 |
269 | * [Kotlin 语言中文站](https://www.kotlincn.net/docs/reference/)
270 | * [Kotlin 的变量、函数和类型](https://juejin.cn/post/6844903918888026126)
271 | * [Kotlin 里那些「不是那么写的」](https://juejin.cn/post/6844903920536551431)
272 | * [Kotlin 的协程用力瞥一眼](https://juejin.cn/post/6844903949686800392)
273 | * [Kotlin 里那些「更方便的」](https://juejin.cn/post/6844903923061358605)
274 | * [万字长文 - Kotlin 协程进阶](https://juejin.cn/post/6950616789390721037)
275 | * [Kotlin Coroutines Flow 系列(二) Flow VS RxJava2](https://juejin.cn/post/6844904057534939149)
276 | * [Kotlin 协程实战进阶](https://blog.csdn.net/m0_37796683/article/details/119424009)
277 | * [Kotlin系列文章](https://blog.csdn.net/m0_37796683/category_10088599.html)
278 |
279 | ## 如果觉得项目还不错,可以考虑打赏一波
280 |
281 | > 你的打赏是我维护的动力,我将会列出所有打赏人员的清单在下方作为凭证,打赏前请留下打赏项目的备注!
282 |
283 | 
284 |
285 | ## 联系方式
286 |
287 | > 更多资讯内容,欢迎扫描关注我的个人微信公众号:【我的Android开源之旅】
288 |
289 | 
290 |
--------------------------------------------------------------------------------
/app/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/app/build.gradle:
--------------------------------------------------------------------------------
1 | plugins {
2 | id 'com.android.application'
3 | id 'kotlin-android'
4 | }
5 | apply plugin: 'img-optimizer'
6 | //打包时,记得设置true启用
7 | if (isNeedPackage.toBoolean() && isUseBooster.toBoolean()) {
8 | apply plugin: 'com.didiglobal.booster'
9 | }
10 |
11 | android {
12 | compileSdkVersion build_versions.target_sdk
13 | buildToolsVersion build_versions.build_tools
14 |
15 | defaultConfig {
16 | applicationId "com.xuexiang.kotlinsample"
17 | minSdkVersion build_versions.min_sdk
18 | targetSdkVersion build_versions.target_sdk
19 | versionCode 1
20 | versionName "1.0"
21 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
22 |
23 | multiDexEnabled true
24 | vectorDrawables.useSupportLibrary = true
25 |
26 | javaCompileOptions {
27 | annotationProcessorOptions {
28 | arguments = [moduleName: project.getName()]
29 | }
30 | }
31 | }
32 |
33 | signingConfigs {
34 | if (isNeedPackage.toBoolean()) {
35 | release {
36 | storeFile file(app_release.storeFile)
37 | storePassword app_release.storePassword
38 | keyAlias app_release.keyAlias
39 | keyPassword app_release.keyPassword
40 | }
41 | }
42 | debug {
43 | storeFile file("./debug.jks")
44 | storePassword "123456"
45 | keyAlias "debug"
46 | keyPassword "123456"
47 | }
48 | }
49 |
50 | buildTypes {
51 | release {
52 | minifyEnabled true
53 | shrinkResources true
54 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
55 | if (isNeedPackage.toBoolean()) {
56 | signingConfig signingConfigs.release
57 |
58 | Properties properties = new Properties()
59 | properties.load(project.rootProject.file('local.properties').newDataInputStream())
60 | def appID = properties.getProperty("APP_ID_UMENG")
61 | if (appID != null) {
62 | buildConfigField "String", "APP_ID_UMENG", appID
63 | } else {
64 | buildConfigField "String", "APP_ID_UMENG", '""'
65 | }
66 | } else {
67 | signingConfig signingConfigs.debug
68 | buildConfigField "String", "APP_ID_UMENG", '""'
69 | }
70 | }
71 |
72 | debug {
73 | debuggable true
74 | minifyEnabled false
75 |
76 | signingConfig signingConfigs.debug
77 | buildConfigField "String", "APP_ID_UMENG", '""'
78 | }
79 | }
80 |
81 | lintOptions {
82 | abortOnError false
83 | }
84 |
85 | compileOptions {
86 | sourceCompatibility JavaVersion.VERSION_1_8
87 | targetCompatibility JavaVersion.VERSION_1_8
88 | }
89 |
90 | buildFeatures {
91 | viewBinding true
92 | }
93 | }
94 |
95 | dependencies {
96 | implementation fileTree(dir: 'libs', include: ['*.jar'])
97 | testImplementation deps.junit
98 | androidTestImplementation 'androidx.test.ext:junit:1.1.3'
99 | androidTestImplementation deps.espresso.core
100 |
101 | implementation 'androidx.core:core-ktx:1.7.0'
102 | implementation "org.jetbrains.kotlin:kotlin-reflect:1.7.20"
103 |
104 | implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.4"
105 | implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.6.4"
106 |
107 | // lifecycle对于协程的扩展封装
108 | implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.4.1"
109 | implementation "androidx.lifecycle:lifecycle-runtime-ktx:2.4.1"
110 | implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.4.1"
111 |
112 | // XTask
113 | implementation 'com.github.xuexiangjys.XTask:xtask-core:1.0.2'
114 |
115 | implementation deps.androidx.multidex
116 | //屏幕适配AutoSize
117 | implementation 'me.jessyan:autosize:1.2.1'
118 | //umeng统计
119 | implementation 'com.umeng.umsdk:common:9.3.8'
120 | implementation 'com.umeng.umsdk:asms:1.2.1'
121 |
122 | //美团多渠道打包
123 | implementation 'com.meituan.android.walle:library:1.1.6'
124 | }
125 |
126 | //x-library依赖脚本
127 | apply from: 'x-library-simple.gradle'
128 | //walle多渠道打包
129 | apply from: 'multiple-channel.gradle'
130 |
131 |
--------------------------------------------------------------------------------
/app/channel:
--------------------------------------------------------------------------------
1 | # 美团
2 | meituan
3 | # 三星
4 | samsungapps
5 | # 小米
6 | xiaomi
7 | # 91助手
8 | 91com
9 | # 魅族
10 | meizu
11 | # 豌豆荚
12 | wandou
13 | # Google Play
14 | googleplay
15 | # 百度
16 | baidu
17 | # 360
18 | 360cn
19 | # 应用宝
20 | myapp
21 | # 华为
22 | huawei
23 | # 蒲公英
24 | pgyer
25 | github
--------------------------------------------------------------------------------
/app/debug.jks:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xuexiangjys/KotlinSample/c9145ad5e302f89b122a2ac95049c8d12cf4cd06/app/debug.jks
--------------------------------------------------------------------------------
/app/multiple-channel.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'walle'
2 |
3 | walle {
4 | // 指定渠道包的输出路径
5 | apkOutputFolder = new File("${project.buildDir}/outputs/channels")
6 | // 定制渠道包的APK的文件名称
7 | apkFileNameFormat = '${appName}-${packageName}-${channel}-${buildType}-v${versionName}-${versionCode}-${buildTime}.apk'
8 | // 渠道配置文件
9 | channelFile = new File("${project.getProjectDir()}/channel")
10 | }
--------------------------------------------------------------------------------
/app/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | #=========================================基础不变的混淆配置=========================================##
2 | #指定代码的压缩级别
3 | -optimizationpasses 5
4 | #包名不混合大小写
5 | -dontusemixedcaseclassnames
6 | #不去忽略非公共的库类
7 | -dontskipnonpubliclibraryclasses
8 | # 指定不去忽略非公共的库的类的成员
9 | -dontskipnonpubliclibraryclassmembers
10 | #优化 不优化输入的类文件
11 | -dontoptimize
12 | #预校验
13 | -dontpreverify
14 | #混淆时是否记录日志
15 | -verbose
16 | # 混淆时所采用的算法
17 | -optimizations !code/simplification/arithmetic,!field/*,!class/merging/*
18 | #保护注解
19 | -keepattributes *Annotation*
20 | #忽略警告
21 | -ignorewarnings
22 |
23 | ##记录生成的日志数据,gradle build时在本项目根目录输出##
24 | #apk 包内所有 class 的内部结构
25 | -dump class_files.txt
26 | #未混淆的类和成员
27 | -printseeds seeds.txt
28 | #列出从 apk 中删除的代码
29 | -printusage unused.txt
30 | #混淆前后的映射
31 | -printmapping mapping.txt
32 | # 并保留源文件名为"Proguard"字符串,而非原始的类名 并保留行号
33 | -keepattributes SourceFile,LineNumberTable
34 | ########记录生成的日志数据,gradle build时 在本项目根目录输出-end#####
35 |
36 | #需要保留的东西
37 | # 保持哪些类不被混淆
38 | -keep public class * extends android.app.Fragment
39 | -keep public class * extends android.app.Activity
40 | -keep public class * extends android.app.Application
41 | -keep public class * extends android.app.Service
42 | -keep public class * extends android.content.BroadcastReceiver
43 | -keep public class * extends android.content.ContentProvider
44 | -keep public class * extends android.app.backup.BackupAgentHelper
45 | -keep public class * extends android.preference.Preference
46 | -keep public class * extends android.support.v4.**
47 | -keep public class com.android.vending.licensing.ILicensingService
48 |
49 | #如果有引用v4包可以添加下面这行
50 | -keep public class * extends android.support.v4.app.Fragment
51 |
52 | ##########JS接口类不混淆,否则执行不了
53 | -dontwarn com.android.JsInterface.**
54 | -keep class com.android.JsInterface.** {*; }
55 |
56 | #极光推送和百度lbs android sdk一起使用proguard 混淆的问题#http的类被混淆后,导致apk定位失败,保持apache 的http类不被混淆就好了
57 | -dontwarn org.apache.**
58 | -keep class org.apache.**{ *; }
59 |
60 | -keep public class * extends android.view.View {
61 | public (android.content.Context);
62 | public (android.content.Context, android.util.AttributeSet);
63 | public (android.content.Context, android.util.AttributeSet, int);
64 | public void set*(...);
65 | }
66 |
67 | #保持 native 方法不被混淆
68 | -keepclasseswithmembernames class * {
69 | native ;
70 | }
71 |
72 | #保持自定义控件类不被混淆
73 | -keepclasseswithmembers class * {
74 | public (android.content.Context, android.util.AttributeSet);
75 | }
76 |
77 | #保持自定义控件类不被混淆
78 | -keepclassmembers class * extends android.app.Activity {
79 | public void *(android.view.View);
80 | }
81 |
82 | #保持 Parcelable 不被混淆
83 | -keep class * implements android.os.Parcelable {
84 | public static final android.os.Parcelable$Creator *;
85 | }
86 |
87 | #保持 Serializable 不被混淆
88 | -keepnames class * implements java.io.Serializable
89 |
90 | #保持 Serializable 不被混淆并且enum 类也不被混淆
91 | -keepclassmembers class * implements java.io.Serializable {
92 | static final long serialVersionUID;
93 | private static final java.io.ObjectStreamField[] serialPersistentFields;
94 | !static !transient ;
95 | !private ;
96 | !private ;
97 | private void writeObject(java.io.ObjectOutputStream);
98 | private void readObject(java.io.ObjectInputStream);
99 | java.lang.Object writeReplace();
100 | java.lang.Object readResolve();
101 | }
102 |
103 | #保持枚举 enum 类不被混淆 如果混淆报错,建议直接使用上面的 -keepclassmembers class * implements java.io.Serializable即可
104 | -keepclassmembers enum * {
105 | public static **[] values();
106 | public static ** valueOf(java.lang.String);
107 | }
108 |
109 | -keepclassmembers class * {
110 | public void *ButtonClicked(android.view.View);
111 | }
112 |
113 | #不混淆资源类
114 | -keep class **.R$* {*;}
115 |
116 | #===================================混淆保护自己项目的部分代码以及引用的第三方jar包library=============================#######
117 | #如果引用了v4或者v7包
118 | -dontwarn android.support.**
119 |
120 |
121 | # AndroidX 防止混淆
122 | -dontwarn com.google.android.material.**
123 | -dontnote com.google.android.material.**
124 | -dontwarn androidx.**
125 | -keep class com.google.android.material.** {*;}
126 | -keep class androidx.** {*;}
127 | -keep public class * extends androidx.**
128 | -keep interface androidx.** {*;}
129 | -keepclassmembers class * {
130 | @androidx.annotation.Keep *;
131 | }
132 |
133 | # zxing
134 | -dontwarn com.google.zxing.**
135 | -keep class com.google.zxing.**{*;}
136 |
137 | #SignalR推送
138 | -keep class microsoft.aspnet.signalr.** { *; }
139 |
140 | # 极光推送混淆
141 | -dontoptimize
142 | -dontpreverify
143 | -dontwarn cn.jpush.**
144 | -keep class cn.jpush.** { *; }
145 | -dontwarn cn.jiguang.**
146 | -keep class cn.jiguang.** { *; }
147 |
148 | # 数据库框架OrmLite
149 | -keepattributes *DatabaseField*
150 | -keepattributes *DatabaseTable*
151 | -keepattributes *SerializedName*
152 | -keep class com.j256.**
153 | -keepclassmembers class com.j256.** { *; }
154 | -keep enum com.j256.**
155 | -keepclassmembers enum com.j256.** { *; }
156 | -keep interface com.j256.**
157 | -keepclassmembers interface com.j256.** { *; }
158 |
159 | #XHttp2
160 | -keep class com.xuexiang.xhttp2.model.** { *; }
161 | -keep class com.xuexiang.xhttp2.cache.model.** { *; }
162 | -keep class com.xuexiang.xhttp2.cache.stategy.**{*;}
163 | -keep class com.xuexiang.xhttp2.annotation.** { *; }
164 |
165 | #okhttp
166 | -dontwarn com.squareup.okhttp3.**
167 | -keep class com.squareup.okhttp3.** { *;}
168 | -dontwarn okio.**
169 | -dontwarn javax.annotation.Nullable
170 | -dontwarn javax.annotation.ParametersAreNonnullByDefault
171 | -dontwarn javax.annotation.**
172 |
173 | #如果用到Gson解析包的,直接添加下面这几行就能成功混淆,不然会报错
174 | -keepattributes Signature
175 | -keep class com.google.gson.stream.** { *; }
176 | -keepattributes EnclosingMethod
177 | -keep class org.xz_sale.entity.**{*;}
178 | -keep class com.google.gson.** {*;}
179 | -keep class com.google.**{*;}
180 | -keep class sun.misc.Unsafe { *; }
181 | -keep class com.google.gson.stream.** { *; }
182 | -keep class com.google.gson.examples.android.model.** { *; }
183 |
184 | # Glide
185 | -keep public class * implements com.bumptech.glide.module.GlideModule
186 | -keep public class * extends com.bumptech.glide.module.AppGlideModule
187 | -keep public enum com.bumptech.glide.load.ImageHeaderParser$** {
188 | **[] $VALUES;
189 | public *;
190 | }
191 |
192 | # Retrofit
193 | -dontwarn retrofit2.**
194 | -keep class retrofit2.** { *; }
195 | -keepattributes Exceptions
196 |
197 | # RxJava RxAndroid
198 | -dontwarn sun.misc.**
199 | -keepclassmembers class rx.internal.util.unsafe.*ArrayQueue*Field* {
200 | long producerIndex;
201 | long consumerIndex;
202 | }
203 | -keepclassmembers class rx.internal.util.unsafe.BaseLinkedQueueProducerNodeRef {
204 | rx.internal.util.atomic.LinkedQueueNode producerNode;
205 | }
206 | -keepclassmembers class rx.internal.util.unsafe.BaseLinkedQueueConsumerNodeRef {
207 | rx.internal.util.atomic.LinkedQueueNode consumerNode;
208 | }
209 |
210 | -dontwarn okio.**
211 | -dontwarn javax.annotation.Nullable
212 | -dontwarn javax.annotation.ParametersAreNonnullByDefault
213 | -dontwarn javax.annotation.**
214 |
215 | # fastjson
216 | -dontwarn com.alibaba.fastjson.**
217 | -keep class com.alibaba.fastjson.** { *; }
218 | -keepattributes Signature
219 |
220 | # xpage
221 | -keep class com.xuexiang.xpage.annotation.** { *; }
222 | -keep class com.xuexiang.xpage.config.** { *; }
223 |
224 | # xaop
225 | -keep @com.xuexiang.xaop.annotation.* class * {*;}
226 | -keep @org.aspectj.lang.annotation.* class * {*;}
227 | -keep class * {
228 | @com.xuexiang.xaop.annotation.* ;
229 | @org.aspectj.lang.annotation.* ;
230 | }
231 | -keepclassmembers class * {
232 | @com.xuexiang.xaop.annotation.* ;
233 | @org.aspectj.lang.annotation.* ;
234 | }
235 |
236 | # xrouter
237 | -keep public class com.xuexiang.xrouter.routes.**{*;}
238 | -keep class * implements com.xuexiang.xrouter.facade.template.ISyringe{*;}
239 | # 如果使用了 byType 的方式获取 Service,需添加下面规则,保护接口
240 | -keep interface * implements com.xuexiang.xrouter.facade.template.IProvider
241 | # 如果使用了 单类注入,即不定义接口实现 IProvider,需添加下面规则,保护实现
242 | -keep class * implements com.xuexiang.xrouter.facade.template.IProvider
243 |
244 | # xupdate
245 | -keep class com.xuexiang.xupdate.entity.** { *; }
246 |
247 | # xvideo
248 | -keep class com.xuexiang.xvideo.jniinterface.** { *; }
249 |
250 | # xipc
251 | -keep @com.xuexiang.xipc.annotation.* class * {*;}
252 | -keep class * {
253 | @com.xuexiang.xipc.annotation.* ;
254 | }
255 | -keepclassmembers class * {
256 | @com.xuexiang.xipc.annotation.* ;
257 | }
258 |
259 | # umeng统计
260 | -keep class com.umeng.** {*;}
261 | -keepclassmembers class * {
262 | public (org.json.JSONObject);
263 | }
264 | -keepclassmembers enum * {
265 | public static **[] values();
266 | public static ** valueOf(java.lang.String);
267 | }
268 |
269 | # materialedittext
270 | -keep class com.xuexiang.xui.widget.edittext.materialedittext.** { *; }
271 |
--------------------------------------------------------------------------------
/app/src/androidTest/java/com/xuexiang/kotlinsample/ExampleInstrumentedTest.kt:
--------------------------------------------------------------------------------
1 | package com.xuexiang.kotlinsample
2 |
3 | import androidx.test.ext.junit.runners.AndroidJUnit4
4 | import androidx.test.platform.app.InstrumentationRegistry
5 | import org.junit.Assert
6 | import org.junit.Test
7 | import org.junit.runner.RunWith
8 |
9 | /**
10 | * Instrumented test, which will execute on an Android device.
11 | *
12 | * @see [Testing documentation](http://d.android.com/tools/testing)
13 | */
14 | @RunWith(AndroidJUnit4::class)
15 | class ExampleInstrumentedTest {
16 | @Test
17 | fun useAppContext() {
18 | // Context of the app under test.
19 | val appContext = InstrumentationRegistry.getInstrumentation().targetContext
20 | Assert.assertEquals("com.xuexiang.kotlinsample", appContext.packageName)
21 | }
22 | }
--------------------------------------------------------------------------------
/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
7 |
8 |
9 |
20 |
21 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
39 |
40 |
41 |
44 |
47 |
48 |
49 |
50 |
--------------------------------------------------------------------------------
/app/src/main/java/com/xuexiang/kotlinsample/MyApp.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2019 xuexiangjys(xuexiangjys@163.com)
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | *
16 | */
17 | package com.xuexiang.kotlinsample
18 |
19 | import android.app.Application
20 | import android.content.Context
21 | import androidx.multidex.MultiDex
22 | import com.xuexiang.kotlinsample.utils.sdkinit.UMengInit
23 | import com.xuexiang.kotlinsample.utils.sdkinit.XBasicLibInit
24 | import com.xuexiang.xtask.XTask
25 |
26 | /**
27 | * @author xuexiang
28 | * @since 2018/11/7 下午1:12
29 | */
30 | class MyApp : Application() {
31 | override fun attachBaseContext(base: Context) {
32 | super.attachBaseContext(base)
33 | //解决4.x运行崩溃的问题
34 | MultiDex.install(this)
35 | }
36 |
37 | override fun onCreate() {
38 | super.onCreate()
39 | initLibs()
40 |
41 | // 设置XTask的调试模式
42 | XTask.debug(isDebug)
43 | }
44 |
45 | /**
46 | * 初始化基础库
47 | */
48 | private fun initLibs() {
49 | XBasicLibInit.init(this)
50 | UMengInit.init(this)
51 | }
52 |
53 | companion object {
54 | /**
55 | * @return 当前app是否是调试开发模式
56 | */
57 | val isDebug: Boolean
58 | get() = BuildConfig.DEBUG
59 | }
60 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/xuexiang/kotlinsample/activity/MainActivity.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2019 xuexiangjys(xuexiangjys@163.com)
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | *
16 | */
17 | package com.xuexiang.kotlinsample.activity
18 |
19 | import android.os.Bundle
20 | import androidx.viewbinding.ViewBinding
21 | import com.xuexiang.kotlinsample.core.BaseActivity
22 | import com.xuexiang.kotlinsample.fragment.MainFragment
23 |
24 | /**
25 | * 程序入口,空壳容器
26 | *
27 | * @author xuexiang
28 | * @since 2019-07-07 23:53
29 | */
30 | class MainActivity : BaseActivity() {
31 |
32 | override fun onCreate(savedInstanceState: Bundle?) {
33 | super.onCreate(savedInstanceState)
34 | openPage(MainFragment::class.java)
35 | }
36 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/xuexiang/kotlinsample/core/BaseActivity.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2019 xuexiangjys(xuexiangjys@163.com)
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | *
16 | */
17 | package com.xuexiang.kotlinsample.core
18 |
19 | import android.content.Context
20 | import android.os.Bundle
21 | import android.view.LayoutInflater
22 | import android.view.View
23 | import androidx.viewbinding.ViewBinding
24 | import com.xuexiang.xpage.base.XPageActivity
25 | import com.xuexiang.xpage.base.XPageFragment
26 | import com.xuexiang.xpage.core.CoreSwitchBean
27 | import com.xuexiang.xrouter.facade.service.SerializationService
28 | import com.xuexiang.xrouter.launcher.XRouter
29 | import io.github.inflationx.viewpump.ViewPumpContextWrapper
30 |
31 | /**
32 | * 基础容器Activity
33 | *
34 | * @author XUE
35 | * @since 2019/3/22 11:21
36 | */
37 | open class BaseActivity : XPageActivity() {
38 |
39 | /**
40 | * ViewBinding
41 | */
42 | var binding: Binding? = null
43 | protected set
44 |
45 | override fun attachBaseContext(newBase: Context) {
46 | //注入字体
47 | super.attachBaseContext(ViewPumpContextWrapper.wrap(newBase))
48 | }
49 |
50 | override fun getCustomRootView(): View? {
51 | binding = viewBindingInflate(layoutInflater)
52 | return binding?.root
53 | }
54 |
55 | override fun onCreate(savedInstanceState: Bundle?) {
56 | initStatusBarStyle()
57 | super.onCreate(savedInstanceState)
58 | }
59 |
60 | /**
61 | * 构建ViewBinding
62 | *
63 | * @param inflater inflater
64 | * @return ViewBinding
65 | */
66 | protected fun viewBindingInflate(inflater: LayoutInflater?): Binding? {
67 | return null
68 | }
69 |
70 | /**
71 | * 初始化状态栏的样式
72 | */
73 | protected fun initStatusBarStyle() {}
74 |
75 | /**
76 | * 打开fragment
77 | *
78 | * @param clazz 页面类
79 | * @param addToBackStack 是否添加到栈中
80 | * @return 打开的fragment对象
81 | */
82 | fun openPage(clazz: Class?, addToBackStack: Boolean): T {
83 | val page = CoreSwitchBean(clazz)
84 | .setAddToBackStack(addToBackStack)
85 | return openPage(page) as T
86 | }
87 |
88 | /**
89 | * 打开fragment
90 | *
91 | * @return 打开的fragment对象
92 | */
93 | fun openNewPage(clazz: Class?): T {
94 | val page = CoreSwitchBean(clazz)
95 | .setNewActivity(true)
96 | return openPage(page) as T
97 | }
98 |
99 | /**
100 | * 切换fragment
101 | *
102 | * @param clazz 页面类
103 | * @return 打开的fragment对象
104 | */
105 | fun switchPage(clazz: Class?): T {
106 | return openPage(clazz, false)
107 | }
108 |
109 | /**
110 | * 序列化对象
111 | *
112 | * @param object
113 | * @return
114 | */
115 | fun serializeObject(`object`: Any?): String {
116 | return XRouter.getInstance().navigation(SerializationService::class.java)
117 | .object2Json(`object`)
118 | }
119 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/xuexiang/kotlinsample/core/BaseContainerFragment.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2019 xuexiangjys(xuexiangjys@163.com)
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | *
16 | */
17 | package com.xuexiang.kotlinsample.core
18 |
19 | import android.content.res.Configuration
20 | import android.view.View
21 | import android.view.ViewGroup
22 | import android.widget.AdapterView
23 | import com.umeng.analytics.MobclickAgent
24 | import com.xuexiang.xaop.annotation.SingleClick
25 | import com.xuexiang.xpage.base.XPageContainerListFragment
26 | import com.xuexiang.xui.widget.actionbar.TitleBar
27 | import com.xuexiang.xui.widget.actionbar.TitleUtils
28 | import java.util.*
29 |
30 | /**
31 | * 修改列表样式为主副标题显示
32 | *
33 | * @author xuexiang
34 | * @since 2018/11/22 上午11:26
35 | */
36 | abstract class BaseContainerFragment : XPageContainerListFragment() {
37 |
38 | override fun initPage() {
39 | initTitle()
40 | initViews()
41 | initListeners()
42 | }
43 |
44 | protected open fun initTitle(): TitleBar? {
45 | return TitleUtils.addTitleBarDynamic(rootView as ViewGroup, pageTitle) { popToBack() }
46 | }
47 |
48 | override fun initData() {
49 | mSimpleData = initSimpleData(mSimpleData)
50 | val data: MutableList