├── .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 | 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 | ![pay.png](https://raw.githubusercontent.com/xuexiangjys/Resource/master/img/pay/pay.png) 284 | 285 | ## 联系方式 286 | 287 | > 更多资讯内容,欢迎扫描关注我的个人微信公众号:【我的Android开源之旅】 288 | 289 | ![](https://s1.ax1x.com/2022/04/27/LbGMJH.jpg) 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?> = ArrayList() 51 | for (content in mSimpleData) { 52 | val item: MutableMap = HashMap() 53 | val index = content.indexOf("\n") 54 | if (index > 0) { 55 | item[SimpleListAdapter.KEY_TITLE] = content.subSequence(0, index).toString() 56 | item[SimpleListAdapter.KEY_SUB_TITLE] = content.subSequence(index + 1, content.length).toString() 57 | } else { 58 | item[SimpleListAdapter.KEY_TITLE] = content 59 | item[SimpleListAdapter.KEY_SUB_TITLE] = "" 60 | } 61 | data.add(item) 62 | } 63 | listView.adapter = SimpleListAdapter(context, data) 64 | initSimply() 65 | } 66 | 67 | override fun onItemClick(adapterView: AdapterView<*>?, view: View, position: Int, id: Long) { 68 | onItemClick(view, position) 69 | } 70 | 71 | @SingleClick 72 | private fun onItemClick(view: View, position: Int) { 73 | onItemClick(position) 74 | } 75 | 76 | override fun onDestroyView() { 77 | listView.onItemClickListener = null 78 | super.onDestroyView() 79 | } 80 | 81 | override fun onConfigurationChanged(newConfig: Configuration) { 82 | //屏幕旋转时刷新一下title 83 | super.onConfigurationChanged(newConfig) 84 | val root = rootView as ViewGroup 85 | if (root.getChildAt(0) is TitleBar) { 86 | root.removeViewAt(0) 87 | initTitle() 88 | } 89 | } 90 | 91 | override fun onResume() { 92 | super.onResume() 93 | MobclickAgent.onPageStart(pageName) 94 | } 95 | 96 | override fun onPause() { 97 | super.onPause() 98 | MobclickAgent.onPageEnd(pageName) 99 | } 100 | } -------------------------------------------------------------------------------- /app/src/main/java/com/xuexiang/kotlinsample/core/SimpleListAdapter.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.view.View 21 | import android.widget.TextView 22 | import com.xuexiang.kotlinsample.R 23 | import com.xuexiang.xui.adapter.listview.BaseListAdapter 24 | import com.xuexiang.xutil.common.StringUtils 25 | 26 | /** 27 | * 主副标题显示适配器 28 | * 29 | * @author xuexiang 30 | * @since 2018/12/19 上午12:19 31 | */ 32 | class SimpleListAdapter(context: Context?, data: List?>?) : BaseListAdapter, SimpleListAdapter.ViewHolder>(context, data) { 33 | override fun newViewHolder(convertView: View): ViewHolder { 34 | val holder = ViewHolder() 35 | holder.mTvTitle = convertView.findViewById(R.id.tv_title) 36 | holder.mTvSubTitle = convertView.findViewById(R.id.tv_sub_title) 37 | return holder 38 | } 39 | 40 | override fun getLayoutId(): Int { 41 | return R.layout.adapter_item_simple_list_2 42 | } 43 | 44 | override fun convert(holder: ViewHolder, item: Map, position: Int) { 45 | holder.mTvTitle!!.text = item[KEY_TITLE] 46 | if (!StringUtils.isEmpty(item[KEY_SUB_TITLE])) { 47 | holder.mTvSubTitle!!.text = item[KEY_SUB_TITLE] 48 | holder.mTvSubTitle!!.visibility = View.VISIBLE 49 | } else { 50 | holder.mTvSubTitle!!.visibility = View.GONE 51 | } 52 | } 53 | 54 | class ViewHolder { 55 | /** 56 | * 标题 57 | */ 58 | var mTvTitle: TextView? = null 59 | 60 | /** 61 | * 副标题 62 | */ 63 | var mTvSubTitle: TextView? = null 64 | } 65 | 66 | companion object { 67 | const val KEY_TITLE = "title" 68 | const val KEY_SUB_TITLE = "sub_title" 69 | } 70 | } -------------------------------------------------------------------------------- /app/src/main/java/com/xuexiang/kotlinsample/fragment/CoroutinesFragment.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.fragment 18 | 19 | import com.xuexiang.kotlinsample.core.BaseContainerFragment 20 | import com.xuexiang.kotlinsample.fragment.coroutines.CoroutinesBasicFragment 21 | import com.xuexiang.kotlinsample.fragment.coroutines.CoroutinesFlowFragment 22 | import com.xuexiang.kotlinsample.fragment.coroutines.CoroutinesXTaskFragment 23 | import com.xuexiang.kotlinsample.fragment.coroutines.SchedulerChangeFragment 24 | import com.xuexiang.xpage.annotation.Page 25 | 26 | /** 27 | * 协程使用 28 | * 29 | * @author xuexiang 30 | * @since 2022/3/25 1:42 上午 31 | */ 32 | @Page(name = "协程使用") 33 | class CoroutinesFragment : BaseContainerFragment() { 34 | 35 | override fun getPagesClasses(): Array> { 36 | return arrayOf( 37 | CoroutinesBasicFragment::class.java, 38 | SchedulerChangeFragment::class.java, 39 | CoroutinesFlowFragment::class.java, 40 | CoroutinesXTaskFragment::class.java 41 | ) 42 | } 43 | } -------------------------------------------------------------------------------- /app/src/main/java/com/xuexiang/kotlinsample/fragment/KotlinBasicFragment.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.fragment 18 | 19 | import com.xuexiang.kotlinsample.core.BaseContainerFragment 20 | import com.xuexiang.kotlinsample.fragment.basic.* 21 | import com.xuexiang.xpage.annotation.Page 22 | 23 | /** 24 | * kotlin的基础语法 25 | * 26 | * @author xuexiang 27 | * @since 2022/3/25 1:42 上午 28 | */ 29 | @Page(name = "基础语法") 30 | class KotlinBasicFragment : BaseContainerFragment() { 31 | 32 | override fun getPagesClasses(): Array> { 33 | return arrayOf( 34 | ScopeFunctionFragment::class.java, 35 | VariableFragment::class.java, 36 | BitOperationFragment::class.java, 37 | SimplifyUseFragment::class.java, 38 | LoopControlFragment::class.java, 39 | ReflectFragment::class.java 40 | ) 41 | } 42 | } -------------------------------------------------------------------------------- /app/src/main/java/com/xuexiang/kotlinsample/fragment/MainFragment.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.fragment 18 | 19 | import android.view.KeyEvent 20 | import com.xuexiang.kotlinsample.core.BaseContainerFragment 21 | import com.xuexiang.kotlinsample.utils.XToastUtils 22 | import com.xuexiang.xpage.annotation.Page 23 | import com.xuexiang.xpage.enums.CoreAnim 24 | import com.xuexiang.xui.widget.actionbar.TitleBar 25 | import com.xuexiang.xutil.XUtil 26 | import com.xuexiang.xutil.common.ClickUtils 27 | import com.xuexiang.xutil.common.ClickUtils.OnClick2ExitListener 28 | 29 | @Page(name = "Kotlin使用演示", anim = CoreAnim.none) 30 | class MainFragment : BaseContainerFragment(), OnClick2ExitListener { 31 | override fun getPagesClasses(): Array> { 32 | return arrayOf( //此处填写fragment 33 | CoroutinesFragment::class.java, 34 | KotlinBasicFragment::class.java 35 | ) 36 | } 37 | 38 | override fun initTitle(): TitleBar? { 39 | return super.initTitle()?.setLeftClickListener { ClickUtils.exitBy2Click(2000, this) } 40 | } 41 | 42 | /** 43 | * 菜单、返回键响应 44 | */ 45 | override fun onKeyDown(keyCode: Int, event: KeyEvent): Boolean { 46 | if (keyCode == KeyEvent.KEYCODE_BACK) { 47 | ClickUtils.exitBy2Click(2000, this) 48 | } 49 | return true 50 | } 51 | 52 | override fun onRetry() { 53 | XToastUtils.toast("再按一次退出程序") 54 | } 55 | 56 | override fun onExit() { 57 | XUtil.exitApp() 58 | } 59 | } -------------------------------------------------------------------------------- /app/src/main/java/com/xuexiang/kotlinsample/fragment/basic/BitOperationFragment.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2022 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 | 18 | package com.xuexiang.kotlinsample.fragment.basic 19 | 20 | import android.util.Log 21 | import com.xuexiang.kotlinsample.core.BaseSimpleListFragment 22 | import com.xuexiang.xpage.annotation.Page 23 | 24 | /** 25 | * kotlin中的位运算符 26 | * 27 | * @author xuexiang 28 | * @since 2022/5/24 1:35 上午 29 | */ 30 | @Page(name = "位运算符:and、or、shl、shr") 31 | class BitOperationFragment : BaseSimpleListFragment() { 32 | 33 | private val TAG = "Kotlin-BitOperation" 34 | 35 | override fun initSimpleData(lists: MutableList): MutableList { 36 | lists.add("Kotlin中的 位运算符 只对Int和Long两种 数据类型 起作用") 37 | lists.add("与: and(bits) == &") 38 | lists.add("或: or(bits) == |") 39 | lists.add("左移: shl(bits) == <<") 40 | lists.add("右移: shr(bits) == >>") 41 | return lists 42 | } 43 | 44 | override fun onItemClick(position: Int) { 45 | when (position) { 46 | 1 -> andTest() 47 | 2 -> orTest() 48 | 3 -> shlTest() 49 | 4 -> shrTest() 50 | } 51 | } 52 | 53 | private fun andTest() { 54 | // 0010 55 | val a = 2 56 | // 1010 57 | val b = 10 58 | // 0010 -> 2 59 | Log.e(TAG, "2&10 = ${a.and(b)}") 60 | Log.e(TAG, "2&10 = ${a and b}") 61 | } 62 | 63 | private fun orTest() { 64 | // 0010 65 | val a = 2 66 | // 1001 67 | val b = 9 68 | // 1011 -> 11 69 | Log.e(TAG, "2|9 = ${a.or(b)}") 70 | Log.e(TAG, "2|9 = ${a or b}") 71 | } 72 | 73 | private fun shlTest() { 74 | // 000010 75 | val a = 2 76 | val b = 4 77 | // 100000 -> 32 78 | Log.e(TAG, "2<<4 = ${a.shl(b)}") 79 | Log.e(TAG, "2<<4 = ${a shl b}") 80 | } 81 | 82 | private fun shrTest() { 83 | // 1000000 84 | val a = 64 85 | val b = 3 86 | // 1000 -> 8 87 | Log.e(TAG, "64>>3 = ${a.shr(b)}") 88 | Log.e(TAG, "64>>3 = ${a shr b}") 89 | } 90 | 91 | } -------------------------------------------------------------------------------- /app/src/main/java/com/xuexiang/kotlinsample/fragment/basic/LoopControlFragment.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2022 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 | 18 | package com.xuexiang.kotlinsample.fragment.basic 19 | 20 | import android.util.Log 21 | import com.xuexiang.kotlinsample.core.BaseSimpleListFragment 22 | import com.xuexiang.xpage.annotation.Page 23 | 24 | /** 25 | * 26 | * return。默认从最直接包围它的函数或者匿名函数返回。 27 | * break。终止最直接包围它的循环。 28 | * continue。继续下一次最直接包围它的循环。 29 | * 30 | */ 31 | @Page(name = "循环中的return break continue") 32 | class LoopControlFragment : BaseSimpleListFragment() { 33 | private val TAG = "Kotlin-LoopControl" 34 | 35 | override fun initSimpleData(lists: MutableList): MutableList { 36 | lists.add("return: 默认从最直接包围它的函数或者匿名函数返回") 37 | lists.add("break: 终止最直接包围它的循环") 38 | lists.add("continue: 继续下一次最直接包围它的循环") 39 | lists.add("在foreach中实现break效果") 40 | lists.add("在foreach中实现continue效果") 41 | return lists 42 | } 43 | 44 | override fun onItemClick(position: Int) { 45 | when (position) { 46 | 0 -> returnTest() 47 | 1 -> breakTest() 48 | 2 -> continueTest() 49 | 3 -> foreachBreakTest() 50 | 4 -> foreachContinueTest() 51 | } 52 | } 53 | 54 | private fun returnTest() { 55 | for (i in 1..3) { 56 | for (j in 1..3) { 57 | Log.e(TAG, "i = $i and j = $j") 58 | if (i == 2) return // 当执行到i == 2时,退出整个循环,直接返回.共执行3+1=4次 59 | Log.e(TAG, "this is below if") 60 | } 61 | } 62 | } 63 | 64 | private fun breakTest() { 65 | for (i in 1..3) { 66 | for (j in 1..3) { 67 | Log.e(TAG, "i = $i and j = $j") 68 | if (i == 2) break // 当执行到i == 2时,退出内层循环,直接从i == 3。开始共执行2*3+1=7次 69 | Log.e(TAG, "this is below if") 70 | } 71 | } 72 | } 73 | 74 | private fun continueTest() { 75 | for (i in 1..3) { 76 | for (j in 1..3) { 77 | Log.e(TAG, "i = $i and j = $j") 78 | if (i == 2) continue // i == 2时,下方的日志不执行。共执行9次 79 | Log.e(TAG, "this is below if") 80 | } 81 | } 82 | } 83 | 84 | private fun foreachBreakTest() { 85 | run loop@{ 86 | listOf(1, 2, 3, 4, 5).forEach { 87 | if (it == 3) return@loop // 局部返回到该 lambda 表达式的调用者,即 loop 标记位,跳出循环,等同于loop中的break效果 88 | Log.e(TAG, "it = $it") 89 | } 90 | } 91 | } 92 | 93 | private fun foreachContinueTest() { 94 | listOf(1, 2, 3, 4, 5).forEach { 95 | if (it == 3) return@forEach // 局部返回到该 lambda 表达式的调用者,即 forEach 循环,等同于loop中的continue效果 96 | Log.e(TAG, "it = $it") 97 | } 98 | 99 | listOf(1, 2, 3, 4, 5).forEachIndexed { index, item -> 100 | if (item == 3) return@forEachIndexed // 局部返回到该 lambda 表达式的调用者,即 forEachIndexed 循环,等同于loop中的continue效果 101 | Log.e(TAG, "index = $index, item = $item") 102 | } 103 | } 104 | 105 | } -------------------------------------------------------------------------------- /app/src/main/java/com/xuexiang/kotlinsample/fragment/basic/ReflectFragment.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2022 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 | 18 | package com.xuexiang.kotlinsample.fragment.basic 19 | 20 | import android.util.Log 21 | import com.xuexiang.kotlinsample.core.BaseSimpleListFragment 22 | import com.xuexiang.kotlinsample.fragment.basic.reflect.GoodStudent 23 | import com.xuexiang.kotlinsample.fragment.basic.reflect.Student 24 | import com.xuexiang.xpage.annotation.Page 25 | 26 | /** 27 | * 1.反射设置/获取某个对象的成员属性 28 | * 2.反射设置/获取某个对象的静态属性 29 | * 3.反射执行某对象的成员方法 30 | * 4.反射执行某个类的静态方法 31 | * 5.反射构建实例 32 | * 33 | * @author xuexiang 34 | * @since 2022/11/6 16:05 35 | */ 36 | @Page(name = "Kotlin中的反射") 37 | class ReflectFragment : BaseSimpleListFragment() { 38 | 39 | private val TAG = "Kotlin-Reflect" 40 | 41 | val student = Student(123, "xxxxxx", 25, 0, 100) 42 | 43 | override fun initSimpleData(lists: MutableList): MutableList { 44 | lists.add("反射设置/获取某个对象的成员属性") 45 | lists.add("反射设置/获取某个对象的静态属性") 46 | lists.add("反射执行某对象的成员方法") 47 | lists.add("反射执行某个类的静态方法") 48 | lists.add("反射构建实例") 49 | return lists 50 | } 51 | 52 | override fun onItemClick(position: Int) { 53 | when (position) { 54 | 0 -> fieldTest() 55 | 1 -> staticFieldTest() 56 | 2 -> invokeMethodTest() 57 | 3 -> invokeStaticMethod() 58 | 4 -> newInstanceTest() 59 | } 60 | } 61 | 62 | private fun fieldTest() { 63 | Log.e(TAG, "Student before $student") 64 | student.javaClass.getDeclaredField("Name").run { 65 | isAccessible = true 66 | set(student, "xuexiang") 67 | Log.e(TAG, "Student after $student") 68 | 69 | Log.e(TAG, "Student Name: ${get(student)}") 70 | } 71 | } 72 | 73 | private fun staticFieldTest() { 74 | Student::class.java.getDeclaredField("TotalNumber").run { 75 | isAccessible = true 76 | set(null, 1111) 77 | Log.e(TAG, "TotalNumber = ${get(null)}") 78 | } 79 | } 80 | 81 | private fun invokeMethodTest() { 82 | student.javaClass.getDeclaredMethod("getName", Integer::class.java).run { 83 | isAccessible = true 84 | Log.e(TAG, "invokeMethod: ${invoke(student, 23)}") 85 | } 86 | } 87 | 88 | 89 | private fun invokeStaticMethod() { 90 | Student::class.java.getDeclaredMethod("incrementTotalNumber", Int::class.java).run { 91 | isAccessible = true 92 | Log.e(TAG, "invokeStaticMethod: ${invoke(null, 23)}") 93 | } 94 | } 95 | 96 | private fun newInstanceTest() { 97 | Student::class.java.getDeclaredConstructor(Int::class.java, String::class.java).run { 98 | isAccessible = true 99 | val std = newInstance(666, "xiaohuang") 100 | Log.e(TAG, "newInstance: $std") 101 | GoodStudent::class.java.getDeclaredConstructor(Student::class.java).run { 102 | isAccessible = true 103 | val goodStd = newInstance(std) 104 | Log.e(TAG, "GoodStudent: $goodStd") 105 | } 106 | } 107 | } 108 | 109 | } -------------------------------------------------------------------------------- /app/src/main/java/com/xuexiang/kotlinsample/fragment/basic/ScopeFunctionFragment.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2022 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 | 18 | package com.xuexiang.kotlinsample.fragment.basic 19 | 20 | import android.util.Log 21 | import com.xuexiang.kotlinsample.core.BaseSimpleListFragment 22 | import com.xuexiang.kotlinsample.fragment.coroutines.business.entity.ProductInfo 23 | import com.xuexiang.xpage.annotation.Page 24 | 25 | /** 26 | * let、with、run、apply、also等作用域函数 27 | * 28 | * @author xuexiang 29 | * @since 2022/5/24 1:35 上午 30 | */ 31 | @Page(name = "let、with、run、apply、also") 32 | class ScopeFunctionFragment : BaseSimpleListFragment() { 33 | 34 | private val TAG = "Kotlin-ScopeFunction" 35 | 36 | private val productInfo = ProductInfo("9587", "格力空调", "优质") 37 | 38 | override fun initSimpleData(lists: MutableList): MutableList { 39 | lists.add("【let】函数一般统一做空判断处理") 40 | lists.add("【with】函数在同一个对象的多个方法时,可以省去类名重复") 41 | lists.add("【run】函数适用于`let`函数和`with`函数的任何场景。`run`=`let`+`with`") 42 | lists.add("【apply】函数整体上和`run`函数相似,唯一不同就是它的返回值是对象本身") 43 | lists.add("【also】适用于`let`函数的任何场景,唯一不同就是它的返回值是对象本身") 44 | return lists 45 | } 46 | 47 | override fun onItemClick(position: Int) { 48 | when (position) { 49 | 0 -> letForTest() 50 | 1 -> withForTest() 51 | 2 -> runForTest() 52 | 3 -> applyForTest() 53 | 4 -> alsoForTest() 54 | } 55 | } 56 | 57 | 58 | /** 59 | * `let`函数一般统一做空判断处理。 60 | */ 61 | private fun letForTest() { 62 | val result = productInfo.let { 63 | Log.e(TAG, "let == product:${it.brand}, quality:${it.quality}") 64 | 1111 65 | } 66 | Log.e(TAG, "let == result:$result") 67 | } 68 | 69 | /** 70 | * `with`函数在同一个对象的多个方法时,可以省去类名重复。 71 | */ 72 | private fun withForTest() { 73 | val result = with(productInfo) { 74 | Log.e(TAG, "with == product:$brand, quality:$quality") 75 | 2222 76 | } 77 | Log.e(TAG, "with == result:$result") 78 | } 79 | 80 | /** 81 | * `run`函数适用于`let`函数和`with`函数的任何场景。`run`=`let`+`with`。 82 | */ 83 | private fun runForTest() { 84 | val result = productInfo.run { 85 | Log.e(TAG, "run == product:$brand, quality:$quality") 86 | 3333 87 | } 88 | Log.e(TAG, "run == result:$result") 89 | } 90 | 91 | /** 92 | * `apply`函数整体上和`run`函数相似,唯一不同就是它的返回值是对象本身。 93 | */ 94 | private fun applyForTest() { 95 | val result = productInfo.apply { 96 | Log.e(TAG, "apply == product:$brand, quality:$quality") 97 | } 98 | Log.e(TAG, "apply == result:$result") 99 | } 100 | 101 | /** 102 | * `also`适用于`let`函数的任何场景,唯一不同就是它的返回值是对象本身 103 | */ 104 | private fun alsoForTest() { 105 | val result = productInfo.also { 106 | Log.e(TAG, "also == product:${it.brand}, quality:${it.quality}") 107 | } 108 | Log.e(TAG, "also == result:$result") 109 | } 110 | 111 | } -------------------------------------------------------------------------------- /app/src/main/java/com/xuexiang/kotlinsample/fragment/basic/SimplifyUseFragment.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2022 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 | 18 | package com.xuexiang.kotlinsample.fragment.basic 19 | 20 | import com.xuexiang.kotlinsample.core.BaseContainerFragment 21 | import com.xuexiang.kotlinsample.fragment.basic.simplify.* 22 | import com.xuexiang.xpage.annotation.Page 23 | 24 | /** 25 | * Kotlin中更加方便的写法:https://juejin.cn/post/6844903923061358605 26 | * 27 | * 28 | * @author xuexiang 29 | * @since 2022/5/28 1:51 上午 30 | */ 31 | @Page(name = "Kotlin中常见的便捷使用") 32 | class SimplifyUseFragment : BaseContainerFragment() { 33 | 34 | override fun getPagesClasses(): Array> { 35 | return arrayOf( 36 | StringFragment::class.java, 37 | ArrayFragment::class.java, 38 | ConditionalFragment::class.java, 39 | ExtensionFragment::class.java, 40 | HighFunctionFragment::class.java, 41 | ) 42 | } 43 | } -------------------------------------------------------------------------------- /app/src/main/java/com/xuexiang/kotlinsample/fragment/basic/VariableFragment.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2022 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 | 18 | package com.xuexiang.kotlinsample.fragment.basic 19 | 20 | import android.util.Log 21 | import com.xuexiang.kotlinsample.core.BaseSimpleListFragment 22 | import com.xuexiang.kotlinsample.fragment.basic.simplify.Person 23 | import com.xuexiang.kotlinsample.fragment.coroutines.business.entity.ProductInfo 24 | import com.xuexiang.xpage.annotation.Page 25 | 26 | /** 27 | * 变量基础 28 | * 29 | * var:可变变量 var <表识符> : <类型>? = null/指定值 30 | * val:不可变变量 val <表识符> : <类型>? = null/指定值 31 | * `?`:表示该变量可为空 32 | * !!:不做空检查,判定一定非空,空的话会报错 33 | * lateinit: 修饰var变量,默认你会初始化,不做空检查 34 | * by lazy {}:修饰val变量,程序第一次使用到这个变量(或者对象)时再初始化 35 | * const:修饰val变量,代表常量 36 | * 37 | * @author xuexiang 38 | * @since 2022/5/27 11:22 下午 39 | */ 40 | @Page(name = "变量基础") 41 | class VariableFragment : BaseSimpleListFragment() { 42 | 43 | companion object { 44 | const val TAG = "Kotlin-Variable" 45 | } 46 | 47 | var a: String? = null 48 | 49 | val b = "abc" 50 | 51 | lateinit var c: String 52 | 53 | val d: String by lazy { 54 | Log.e(TAG, "-----lazy init start-----") 55 | "this is a lazy variable" 56 | } 57 | 58 | var e: String? = null 59 | get() = "this is $field" 60 | set(value) { 61 | if (field != value) { 62 | Log.e(TAG, "modify field:$value") 63 | field = value 64 | } else { 65 | Log.e(TAG, "value is equal:$value") 66 | } 67 | 68 | } 69 | 70 | init { 71 | a = "haha!" 72 | } 73 | 74 | 75 | override fun initArgs() { 76 | super.initArgs() 77 | 78 | c = "this is a lateinit variable!" 79 | } 80 | 81 | override fun initSimpleData(lists: MutableList): MutableList { 82 | lists.add("var:可变变量") 83 | lists.add("val:不可变变量") 84 | lists.add("`?`:表示该变量可为空") 85 | lists.add("!!:不做空检查,判定一定非空,空的话会报错") 86 | lists.add("lateinit: 修饰var变量,默认你会初始化,不做空检查") 87 | lists.add("by lazy {}:修饰val变量,程序第一次使用到这个变量(或者对象)时再初始化") 88 | lists.add("const:修饰val变量,代表常量") 89 | lists.add("field的getter/setter函数") 90 | lists.add("类型的判断和强转") 91 | lists.add("可变数量的参数vararg") 92 | lists.add("使用data class的copy()函数进行对象浅拷贝") 93 | return lists 94 | } 95 | 96 | override fun onItemClick(position: Int) { 97 | when (position) { 98 | 5 -> { 99 | Log.e(TAG, "d = $d") 100 | } 101 | 7 -> { 102 | e = ((Math.random() * 3).toInt() + 1).toString() 103 | Log.e(TAG, "e = $e") 104 | } 105 | 8 -> { 106 | Log.e(TAG, getTypeName("hahaha")) 107 | Log.e(TAG, getTypeName(88)) 108 | Log.e(TAG, getTypeName(listOf(1, 2, 3, 4))) 109 | Log.e(TAG, getSomething("hahaha").toString()) 110 | } 111 | 9 -> { 112 | logTxt("a", "b", "c") 113 | } 114 | 10 -> { 115 | val userA = Person("张三", 29, "12341243543SS") 116 | val userB = userA.copy(name = "李四") 117 | Log.e(TAG, "$userA") 118 | Log.e(TAG, "$userB") 119 | } 120 | } 121 | } 122 | 123 | 124 | private fun getTypeName(any: Any) = 125 | when (any) { 126 | is String -> "String $any" 127 | is Int -> "Int ${any.plus(3)}" 128 | is List<*> -> "List ${any.size}" 129 | else -> "Other" 130 | } 131 | 132 | private fun getSomething(any: Any) = 133 | (any as? ProductInfo)?.brand 134 | 135 | 136 | private fun logTxt(vararg value: String) { 137 | value.forEachIndexed { index, item -> 138 | Log.e(TAG, "$index - $item") 139 | } 140 | } 141 | 142 | } -------------------------------------------------------------------------------- /app/src/main/java/com/xuexiang/kotlinsample/fragment/basic/reflect/GoodStudent.java: -------------------------------------------------------------------------------- 1 | package com.xuexiang.kotlinsample.fragment.basic.reflect; 2 | 3 | /** 4 | * 继承了Student,用于测试"如果调用的方法属于该对象的父类,那getDeclaredMethod就会抛异常NoSuchMethodException"的问题 5 | * 6 | * @author xuexiang 7 | * @since 2019/3/4 下午10:12 8 | */ 9 | public class GoodStudent extends Student { 10 | 11 | private int AchievementCount = 3; 12 | 13 | 14 | public GoodStudent(int ID, String name, int age, int sex, int score) { 15 | super(ID, name, age, sex, score); 16 | } 17 | 18 | public GoodStudent(Student student) { 19 | super(student.ID + 1, "xxxx", 22); 20 | } 21 | 22 | public int getAchievementCount() { 23 | return AchievementCount; 24 | } 25 | 26 | public GoodStudent setAchievementCount(int achievementCount) { 27 | AchievementCount = achievementCount; 28 | return this; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /app/src/main/java/com/xuexiang/kotlinsample/fragment/basic/reflect/Student.java: -------------------------------------------------------------------------------- 1 | package com.xuexiang.kotlinsample.fragment.basic.reflect; 2 | 3 | /** 4 | * 学生类 5 | * 6 | * @author xuexiang 7 | * @since 2019/3/4 下午8:36 8 | */ 9 | public class Student { 10 | 11 | /** 12 | * 用于测试反射获取静态属性 13 | */ 14 | private static long TotalNumber = 28; 15 | 16 | public int ID; 17 | 18 | /** 19 | * 用于测试反射获取成员属性 20 | */ 21 | private String Name; 22 | 23 | private int Age = 20; 24 | 25 | private int Sex; 26 | 27 | private int Score; 28 | 29 | private Student() { 30 | 31 | } 32 | 33 | /** 34 | * 用于测试反射构建实例 35 | */ 36 | private Student(int ID, String name) { 37 | this.ID = ID; 38 | Name = name; 39 | } 40 | 41 | public Student(int ID, String name, int age) { 42 | this.ID = ID; 43 | Name = name; 44 | Age = age; 45 | } 46 | 47 | public Student(int ID, String name, int age, int sex, int score) { 48 | this.ID = ID; 49 | Name = name; 50 | Age = age; 51 | Sex = sex; 52 | Score = score; 53 | } 54 | 55 | /** 56 | * 用于测试反射调用成员方法 57 | */ 58 | private String getName(Integer param) { 59 | return Name + param; 60 | } 61 | 62 | public String getName() { 63 | return Name; 64 | } 65 | 66 | /** 67 | * 用于测试反射调用成员方法 68 | */ 69 | private Student setName(String name) { 70 | Name = name; 71 | return this; 72 | } 73 | 74 | /** 75 | * 用于测试反射调用静态方法 76 | */ 77 | private static long incrementTotalNumber(int number) { 78 | return TotalNumber + number; 79 | } 80 | 81 | @Override 82 | public String toString() { 83 | return "Student{" + 84 | "ID=" + ID + 85 | ", Name='" + Name + '\'' + 86 | ", Age=" + Age + 87 | ", Sex=" + Sex + 88 | ", Score=" + Score + 89 | "}, TotalNumber=" + TotalNumber; 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /app/src/main/java/com/xuexiang/kotlinsample/fragment/basic/simplify/ArrayFragment.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2022 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 | 18 | package com.xuexiang.kotlinsample.fragment.basic.simplify 19 | 20 | import android.util.Log 21 | import com.xuexiang.kotlinsample.core.BaseSimpleListFragment 22 | import com.xuexiang.xpage.annotation.Page 23 | 24 | /** 25 | * 数组和集合 26 | * 27 | * @author xuexiang 28 | * @since 2022/6/5 2:34 下午 29 | */ 30 | @Page(name = "数组和集合") 31 | class ArrayFragment : BaseSimpleListFragment() { 32 | 33 | private val TAG = "Kotlin-Array" 34 | 35 | override fun initSimpleData(lists: MutableList): MutableList { 36 | lists.add("创建") 37 | lists.add("forEach:遍历") 38 | lists.add("filter:过滤") 39 | lists.add("map:变换、修改") 40 | lists.add("flatMap:变换、创建、合并") 41 | lists.add("Range:区间范围") 42 | lists.add("Sequence:惰性集合操作") 43 | lists.add("find:寻找第一个符合要求的内容") 44 | lists.add("any:判断是否存在符合要求的内容") 45 | lists.add("count:获取符合要求内容的数量") 46 | lists.add("maxBy:获取最大的内容") 47 | return lists 48 | } 49 | 50 | override fun onItemClick(position: Int) { 51 | when (position) { 52 | 0 -> listCreate() 53 | 1 -> listForEach() 54 | 2 -> listFilter() 55 | 3 -> listMap() 56 | 4 -> listFlatMap() 57 | 5 -> rangeTest() 58 | 6 -> sequenceTest() 59 | 7 -> findTest() 60 | 8 -> anyTest() 61 | 9 -> countTest() 62 | 10 -> maxByTest() 63 | } 64 | } 65 | 66 | private fun listCreate() { 67 | // 数组 68 | val intArray = intArrayOf(1, 2, 3) 69 | // 集合 70 | val intList = listOf(1, 2, 3) 71 | val intSet = setOf(4, 5, 4, 6, 7, 5) 72 | // 可变集合 73 | val mutableList = mutableListOf(1, 2, 3) 74 | mutableList.add(4) 75 | val mutableMap = mutableMapOf( 76 | 1 to "1", 77 | 2 to "2", 78 | 3 to "3" 79 | ) 80 | Log.e(TAG, "intArray $intArray") 81 | Log.e(TAG, "intList $intList") 82 | Log.e(TAG, "intSet $intSet") 83 | Log.e(TAG, "mutableList $mutableList") 84 | Log.e(TAG, "mutableMap $mutableMap") 85 | } 86 | 87 | private fun listForEach() { 88 | intArrayOf(1, 2, 3).forEach { i -> 89 | Log.e(TAG, "遍历:$i") 90 | } 91 | } 92 | 93 | /** 94 | * 遍历每个元素并按给的条件进行过滤,最终形成新的集合 95 | * 96 | * 结果:[4, 8] 97 | */ 98 | private fun listFilter() { 99 | val result = intArrayOf(1, 2, 3, 4, 8).filter { i -> 100 | i > 3 101 | } 102 | Log.e(TAG, "结果:$result") 103 | } 104 | 105 | /** 106 | * 遍历每个元素并执行给定表达式,最终形成新的集合 107 | * 108 | * 结果:[3, 6, 9] 109 | */ 110 | private fun listMap() { 111 | val result = intArrayOf(1, 2, 3).map { i -> 112 | i * 3 113 | } 114 | Log.e(TAG, "结果:$result") 115 | } 116 | 117 | /** 118 | * 遍历每个元素,并为每个元素创建新的集合,最后合并到一个集合中 119 | * 120 | * 结果:[3, a, 6, a, 9, a] 121 | */ 122 | private fun listFlatMap() { 123 | val result = intArrayOf(1, 2, 3).flatMap { i -> 124 | listOf("${i * 3}", "a") // 👈 生成新集合 125 | } 126 | Log.e(TAG, "结果:$result") 127 | } 128 | 129 | /** 130 | * 这里的 0 until 1000 表示从 0 到 1000,但不包括 1000,这就是半开区间 [0, 1000) 。 131 | */ 132 | private fun rangeTest() { 133 | val time = System.currentTimeMillis() - 3 * MINUTE_S * 1000 134 | Log.e(TAG, "结果:${getFuzzyTimeDescriptionByNow(time)}") 135 | } 136 | 137 | /** 138 | * 根据时间戳获取模糊型的时间描述。 139 | * 140 | * @param timestamp 时间戳 单位为毫秒 141 | * @return 模糊型的与当前时间的差 142 | * 143 | * * 如果在 1 分钟内或者时间是未来的时间,显示刚刚 144 | * * 如果在 1 小时内,显示 XXX分钟前 145 | * * 如果在 1 天内,显示XXX小时前 146 | * * 如果在 1 月内,显示XXX天前 147 | * * 如果在 1 年内,显示XXX月前 148 | * * 如果在 1 年外,显示XXX年前 149 | * 150 | */ 151 | private fun getFuzzyTimeDescriptionByNow(timestamp: Long): String { 152 | val currentTime = System.currentTimeMillis() 153 | // 与现在时间相差秒数 154 | val timeStr: String = when (val timeGap = (currentTime - timestamp) / 1000) { 155 | in 0 until MINUTE_S -> "刚刚" 156 | in MINUTE_S until HOUR_S -> "${timeGap.toFloat() / MINUTE_S}分钟前" 157 | in HOUR_S until DAY_S -> "${timeGap.toFloat() / HOUR_S}小时前" 158 | in DAY_S until MONTH_S -> "${timeGap.toFloat() / DAY_S}天前" 159 | in MONTH_S until YEAR_S -> "${timeGap.toFloat() / MONTH_S}个月前" 160 | else -> "${timeGap.toFloat() / YEAR_S}年前" 161 | } 162 | return timeStr 163 | } 164 | 165 | /** 166 | * 惰性指当出现满足条件的第一个元素的时候,Sequence 就不会执行后面的元素遍历. 167 | */ 168 | private fun sequenceTest() { 169 | val sequence = sequenceOf(1, 2, 3, 4) 170 | val result = sequence 171 | .map { i -> 172 | Log.e(TAG, "Map $i") 173 | i * 2 174 | } 175 | .filter { i -> 176 | Log.e(TAG, "Filter $i") 177 | i % 3 == 0 178 | } 179 | Log.e(TAG, "result: ${result.first()}") // 👈 只取集合的第一个元素 180 | } 181 | 182 | private fun findTest() { 183 | val list = listOf(1, 2, 3, 4) 184 | val result = list.find { 185 | it > 2 186 | } 187 | Log.e(TAG, "find: $result") 188 | } 189 | 190 | private fun anyTest() { 191 | val list = listOf(1, 2, 3, 4) 192 | val result = list.any { 193 | it > 2 194 | } 195 | Log.e(TAG, "any: $result") 196 | } 197 | 198 | private fun countTest() { 199 | val list = listOf(1, 2, 3, 4) 200 | val result = list.count { 201 | it > 2 202 | } 203 | Log.e(TAG, "count: $result") 204 | } 205 | 206 | private fun maxByTest() { 207 | val list = listOf(1, 2, 3, 4) 208 | val result = list.maxByOrNull { 209 | it 210 | } 211 | Log.e(TAG, "maxBy: $result") 212 | } 213 | 214 | companion object { 215 | 216 | /** 217 | * 年,单位【s】 218 | */ 219 | private const val YEAR_S = 365 * 24 * 60 * 60 220 | 221 | /** 222 | * 月,单位【s】 223 | */ 224 | private const val MONTH_S = 30 * 24 * 60 * 60 225 | 226 | /** 227 | * 天,单位【s】 228 | */ 229 | private const val DAY_S = 24 * 60 * 60 230 | 231 | /** 232 | * 小时,单位【s】 233 | */ 234 | private const val HOUR_S = 60 * 60 235 | 236 | /** 237 | * 分钟,单位【s】 238 | */ 239 | private const val MINUTE_S = 60 240 | 241 | } 242 | 243 | } -------------------------------------------------------------------------------- /app/src/main/java/com/xuexiang/kotlinsample/fragment/basic/simplify/ConditionalFragment.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2022 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 | 18 | package com.xuexiang.kotlinsample.fragment.basic.simplify 19 | 20 | import android.util.Log 21 | import com.xuexiang.kotlinsample.core.BaseSimpleListFragment 22 | import com.xuexiang.xpage.annotation.Page 23 | 24 | /** 25 | * 条件判断 26 | * 27 | * @author xuexiang 28 | * @since 2022/6/14 12:51 上午 29 | */ 30 | @Page(name = "条件判断") 31 | class ConditionalFragment : BaseSimpleListFragment() { 32 | 33 | private val TAG = "Kotlin-Conditional" 34 | 35 | override fun initSimpleData(lists: MutableList): MutableList { 36 | lists.add("kotlin中 if/else 代替三元运算符") 37 | lists.add("for循环使用in") 38 | lists.add("for循环..和until的区别") 39 | lists.add("?. 和 ?:") 40 | return lists 41 | } 42 | 43 | override fun onItemClick(position: Int) { 44 | when (position) { 45 | 0 -> ifElseTest() 46 | 1 -> forInTest() 47 | 2 -> forUntilTest() 48 | 3 -> nullSafeTest(null) 49 | } 50 | } 51 | 52 | 53 | private fun ifElseTest() { 54 | val a = 10 55 | val b = 20 56 | // 等价于 max = a > b ? a : b 57 | val max = if (a > b) a else b 58 | } 59 | 60 | private fun forInTest() { 61 | val array = intArrayOf(1, 2, 3, 4) 62 | for (item in array) { 63 | Log.e(TAG, "for $item") 64 | } 65 | } 66 | 67 | /** 68 | * 这里的 1..5 表示从 1 到 5,且包括 5,这就是开区间 [1, 5] 69 | * 这里的 1 until 5 表示从 1 到 5,但不包括 5,这就是半开区间 [1, 5)s 70 | */ 71 | private fun forUntilTest() { 72 | // 循环5次,步长为1的递增 73 | for (i in 1..5) { 74 | Log.e(TAG, "in $i") 75 | } 76 | // 1 2 3 4 5 77 | 78 | 79 | // 循环4次,步长为1的递增 80 | for (i in 1 until 5) { 81 | Log.e(TAG, "until $i") 82 | } 83 | // 1 2 3 4 84 | } 85 | 86 | private fun nullSafeTest(str: String?) { 87 | // 如果左侧表达式 str?.length 结果为空,则返回右侧的值 -1。 88 | val length = str?.length ?: -1 89 | } 90 | 91 | } -------------------------------------------------------------------------------- /app/src/main/java/com/xuexiang/kotlinsample/fragment/basic/simplify/Constructor.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2022 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 | 18 | package com.xuexiang.kotlinsample.fragment.basic.simplify 19 | 20 | /** 21 | * 构造方法 22 | * 23 | * @author xuexiang 24 | * @since 2022/5/28 2:01 上午 25 | */ 26 | class User(var name: String, var age: Int) 27 | 28 | class UserA { 29 | var name: String = "xiaoming" 30 | var age: Int = 20 31 | 32 | init { 33 | age = 40 34 | } 35 | } 36 | 37 | class UserB(var name: String = "xiaoming", var age: Int = 20) 38 | 39 | 40 | class User2 constructor(var name: String) { 41 | var age: Int = 20 42 | } 43 | 44 | class User3 { 45 | var name: String = "" 46 | private var age: Int = 0 47 | get() = field * 3 48 | set(value) { 49 | field = value 50 | name = "${field}岁的人" 51 | } 52 | 53 | constructor(name: String, age: Int) { 54 | this.name = name 55 | this.age = age 56 | } 57 | 58 | 59 | } 60 | 61 | /** 62 | * Kotlin 的 data class 默认提供了一种对象拷贝的方式 , 即 data class 类会生成 copy() 方法, 类似java.lang.Object 的 clone() 方法,这是一种浅拷贝 63 | */ 64 | data class Person(var name: String, var age: Int, var phone: String) { 65 | override fun toString(): String { 66 | return "Person(name='$name', age=$age, phone='$phone')" 67 | } 68 | } -------------------------------------------------------------------------------- /app/src/main/java/com/xuexiang/kotlinsample/fragment/basic/simplify/Extend.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2022 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 | 18 | package com.xuexiang.kotlinsample.fragment.basic.simplify 19 | 20 | /** 21 | * 类的继承和接口 22 | * 23 | * --类修饰关键词 24 | * open:表示类可继承,类默认是final的; 25 | * final:表示类不可继承,默认属性; 26 | * abstract:表示抽象类; 27 | * enum:表示枚举类; 28 | * annotation:表示注解类; 29 | * 30 | * --可见性修饰词 31 | * public:表示公有,范围最大,所有调用的地方可见,具有最大的访问权限,可以被其他所有类访问,如果没有声明修饰符则系统会默认使用这个修饰符; 32 | * private:表示私有,范围最小,仅在同一文件可见,只能被自己访问和修改; 33 | * protected:表示私有+子类,同一个文件中或者子类可见,自己和子类及同一包中的类可以访问,不能用于顶层声明; 34 | * internal:表示模块,同一个模块中可见。一个模块可以是一个Maven项目,一个Gradle源集。 35 | * 36 | * @author xuexiang 37 | * @since 2022/5/29 1:00 上午 38 | */ 39 | open class Fruit(var price: Float) 40 | 41 | open class Place(var address: String) 42 | 43 | interface IProduce { 44 | fun produce() 45 | } 46 | 47 | 48 | internal class Apple(var quality: Int, price: Float) : Fruit(price), IProduce { 49 | 50 | override fun produce() { 51 | // do produce 52 | } 53 | } -------------------------------------------------------------------------------- /app/src/main/java/com/xuexiang/kotlinsample/fragment/basic/simplify/Extension.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2022 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 | 18 | package com.xuexiang.kotlinsample.fragment.basic.simplify 19 | 20 | /** 21 | * 拓展函数 22 | * 23 | * @author xuexiang 24 | * @since 2022/7/4 1:42 上午 25 | */ 26 | // 拓展string的方法,计算字符串的真实长度 27 | fun String.getRealLength() = 28 | Regex("[^\\x00-\\xff]").replace( 29 | this, 30 | "**" 31 | ).length -------------------------------------------------------------------------------- /app/src/main/java/com/xuexiang/kotlinsample/fragment/basic/simplify/ExtensionFragment.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2022 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 | 18 | package com.xuexiang.kotlinsample.fragment.basic.simplify 19 | 20 | import android.util.Log 21 | import com.xuexiang.kotlinsample.core.BaseSimpleListFragment 22 | import com.xuexiang.xpage.annotation.Page 23 | 24 | /** 25 | * 拓展函数的使用 26 | * 27 | * @author xuexiang 28 | * @since 2022/7/4 1:50 上午 29 | */ 30 | @Page(name = "拓展函数") 31 | class ExtensionFragment : BaseSimpleListFragment() { 32 | 33 | private val TAG = "Kotlin-Extension" 34 | 35 | override fun initSimpleData(lists: MutableList): MutableList { 36 | lists.add("拓展String的方法,获取字符串的真实长度") 37 | return lists 38 | } 39 | 40 | override fun onItemClick(position: Int) { 41 | when (position) { 42 | 0 -> testString() 43 | } 44 | } 45 | 46 | private fun testString() { 47 | val a = "我是来自1978年的中国人" 48 | val b = "abcdefghijklmn" 49 | Log.e(TAG, "长度:${a.length}, 真实长度:${a.getRealLength()}") 50 | Log.e(TAG, "长度:${b.length}, 真实长度:${b.getRealLength()}") 51 | } 52 | } -------------------------------------------------------------------------------- /app/src/main/java/com/xuexiang/kotlinsample/fragment/basic/simplify/Function.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2022 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 | 18 | package com.xuexiang.kotlinsample.fragment.basic.simplify 19 | 20 | /** 21 | * 函数简化 22 | * 23 | * @author xuexiang 24 | * @since 2022/5/29 1:06 上午 25 | */ 26 | 27 | // 1.标准写法 28 | fun getArea(width: Int, height: Int): Int { 29 | return width * height 30 | } 31 | 32 | // 2.简化写法 33 | fun getArea1(width: Int, height: Int) = width * height 34 | 35 | 36 | // 3.默认值 37 | fun getArea2(width: Int = 0, height: Int = 0) = width * height 38 | 39 | 40 | fun login(user: String, password: String, errorMessage: String) { 41 | 42 | // 本地函数(嵌套函数) 43 | fun validate(value: String, errorMessage: String) { 44 | if (value.isEmpty()) { 45 | throw IllegalArgumentException(errorMessage) 46 | } 47 | } 48 | 49 | validate(user, errorMessage) 50 | validate(password, errorMessage) 51 | } -------------------------------------------------------------------------------- /app/src/main/java/com/xuexiang/kotlinsample/fragment/basic/simplify/HighFunctionFragment.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2022 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 | 18 | package com.xuexiang.kotlinsample.fragment.basic.simplify 19 | 20 | import android.util.Log 21 | import com.xuexiang.kotlinsample.core.BaseSimpleListFragment 22 | import com.xuexiang.xpage.annotation.Page 23 | 24 | /** 25 | * 高阶函数是将 函数 用作[参数]或[返回值]的函数 26 | * 27 | * 1.所有函数类型都有一个圆括号括起来的参数类型列表以及一个返回类型:(A, B) -> C 表示接受类型分别为 A 与 B 两个参数并返回一个 C 类型值的函数类型。 28 | * 参数类型列表可以为空,如 () -> A。Unit 返回类型不可省略。 29 | * 30 | * 2.函数类型可以有一个额外的接收者类型,它在表示法中的点之前指定: 类型 A.(B) -> C 表示可以在 A 的接收者对象上以一个 B 类型参数来调用并返回一个 C 类型值的函数。 31 | * 32 | * 3.挂起函数属于特殊种类的函数类型,它的表示法中有一个 suspend 修饰符 ,例如 suspend () -> Unit 或者 suspend A.(B) -> C。 33 | * 34 | * 4.可以通过使用类型别名给函数类型起一个别称. 如:typealias ClickHandler = (Button, ClickEvent) -> Unit 35 | * 36 | * @author xuexiang 37 | * @since 2022/7/4 1:59 上午 38 | */ 39 | @Page(name = "高阶函数") 40 | class HighFunctionFragment : BaseSimpleListFragment() { 41 | 42 | private val TAG = "Kotlin-HighFunction" 43 | 44 | override fun initSimpleData(lists: MutableList): MutableList { 45 | lists.add("reduce: 集合元素累积操作") 46 | lists.add("foldRight:同reduce,只是可以设置初始值") 47 | lists.add("高阶函数1:函数作为入参") 48 | lists.add("高阶函数2:函数作为返回值") 49 | lists.add("typealias:类型别名,给函数、类、枚举等进行重命名") 50 | return lists 51 | } 52 | 53 | override fun onItemClick(position: Int) { 54 | when (position) { 55 | 0 -> reduceTest() 56 | 1 -> foldRightTest() 57 | 2 -> { 58 | val result = testOperation(1) { value -> value * 3 } 59 | Log.e(TAG, "result:$result") 60 | // 输出:result:3 61 | } 62 | 3 -> { 63 | val operation = getOperation(1) 64 | Log.e(TAG, "operation:${operation(4)}") 65 | // 输出:operation:Operation2:4 66 | } 67 | 4 -> { 68 | val result = getAction().invoke("method", 100) 69 | Log.e(TAG, "result:$result") 70 | // 输出:result:name:method, id:100 71 | } 72 | } 73 | } 74 | 75 | private fun reduceTest() { 76 | val intList = listOf(1, 2, 3, 4) 77 | 78 | val reduce = intList.reduce { acc, i -> 79 | acc + i 80 | } 81 | Log.e(TAG, "reduce:$reduce") 82 | // 输出:10 83 | } 84 | 85 | private fun foldRightTest() { 86 | val intList = listOf(1, 2, 3, 4) 87 | 88 | val fold = intList.foldRight(100) { acc, i -> 89 | acc + i 90 | } 91 | Log.e(TAG, "foldRight:$fold") 92 | // 输出:110 93 | } 94 | 95 | /** 96 | * 高阶函数:函数作为入参 97 | */ 98 | private fun testOperation(value: Int, method: (value: Int) -> Int) = method(value) 99 | 100 | /** 101 | * 高阶函数:函数作为返回值 102 | */ 103 | private fun getOperation(type: Int): (value: Int) -> String = 104 | when (type) { 105 | 0 -> { value -> 106 | "Operation1:$value" 107 | } 108 | 1 -> { value -> 109 | "Operation2:$value" 110 | } 111 | else -> { value -> 112 | "Operation3:$value" 113 | } 114 | } 115 | 116 | private fun getAction() : Action = { name: String, id: Int -> "name:$name, id:$id"} 117 | 118 | } 119 | 120 | // 类型别名 给 函数、类、枚举等进行重命名 121 | typealias Action = (String, Int) -> String 122 | -------------------------------------------------------------------------------- /app/src/main/java/com/xuexiang/kotlinsample/fragment/basic/simplify/InterfaceSample.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2023 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 | 18 | package com.xuexiang.kotlinsample.fragment.basic.simplify 19 | 20 | /** 21 | * interface实例: 22 | * 23 | * object : xx { 24 | * override fun xxx(...) { 25 | * 26 | * } 27 | * } 28 | * 29 | * @author xuexiang 30 | * @since 2023/2/11 18:01 31 | */ 32 | 33 | interface IFilter { 34 | 35 | fun onFilter(quality: Int): Boolean 36 | } 37 | 38 | class Food(var quality: Int) { 39 | 40 | var name: String = "" 41 | 42 | var filter: IFilter? = null 43 | } 44 | 45 | fun setFilter(food: Food) { 46 | food.filter = object : IFilter { 47 | override fun onFilter(quality: Int): Boolean { 48 | return quality > 90 49 | } 50 | } 51 | } -------------------------------------------------------------------------------- /app/src/main/java/com/xuexiang/kotlinsample/fragment/basic/simplify/StringFragment.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2022 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 | 18 | package com.xuexiang.kotlinsample.fragment.basic.simplify 19 | 20 | import android.util.Log 21 | import com.xuexiang.kotlinsample.core.BaseSimpleListFragment 22 | import com.xuexiang.xpage.annotation.Page 23 | 24 | /** 25 | * 字符串 26 | * 27 | * @author xuexiang 28 | * @since 2022/5/28 1:54 上午 29 | */ 30 | @Page(name = "字符串") 31 | class StringFragment : BaseSimpleListFragment() { 32 | 33 | private val TAG = "Kotlin-String" 34 | 35 | override fun initSimpleData(lists: MutableList): MutableList { 36 | lists.add("字符串模板") 37 | lists.add("原生字符串") 38 | lists.add("trimMargin方法") 39 | return lists 40 | } 41 | 42 | override fun onItemClick(position: Int) { 43 | when(position) { 44 | 0 -> stringFormatTest() 45 | 1-> rawStringTest() 46 | 2-> trimMarginTest() 47 | } 48 | } 49 | 50 | private fun stringFormatTest() { 51 | val name = "xuexiangjys" 52 | Log.e(TAG, "the length of $name is ${name.length}") 53 | } 54 | 55 | private fun rawStringTest() { 56 | val string = """ xuexiang \n 57 | | ~~ 35 \?' 58 | """ 59 | Log.e(TAG, string) 60 | } 61 | 62 | 63 | private fun trimMarginTest() { 64 | val string1 = """ xuexiang \n 65 | | ~~ 35 \?' 66 | ?11112234 67 | """.trimMargin() 68 | Log.e(TAG, string1) 69 | 70 | val string2 = """ xuexiang \n 71 | | ~~ 35 \?' 72 | ?11112234 73 | """.trimMargin("?") 74 | Log.e(TAG, string2) 75 | } 76 | 77 | } -------------------------------------------------------------------------------- /app/src/main/java/com/xuexiang/kotlinsample/fragment/coroutines/CoroutinesBasicFragment.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2022 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 | 18 | package com.xuexiang.kotlinsample.fragment.coroutines 19 | 20 | import android.util.Log 21 | import com.xuexiang.kotlinsample.core.BaseSimpleListFragment 22 | import com.xuexiang.xpage.annotation.Page 23 | import kotlinx.coroutines.* 24 | 25 | /** 26 | * CoroutineContext - 协程上下文 27 | * Job: 控制协程的生命周期; 28 | * CoroutineDispatcher: 向合适的线程分发任务; 29 | * CoroutineName: 协程的名称,调试的时候很有用; 30 | * CoroutineExceptionHandler: 处理未被捕捉的异常。 31 | * 32 | * SupervisorJob是一个特殊的 Job,里面的子Job不相互影响,一个子Job失败了,不影响其他子Job的执行。 33 | * 34 | */ 35 | @Page(name = "协程基础使用") 36 | class CoroutinesBasicFragment : BaseSimpleListFragment() { 37 | 38 | private val TAG = "Coroutines-Basic" 39 | 40 | var job: Job? = null 41 | 42 | var lazyJob: Job? = null 43 | 44 | private val mainScope = MainScope() 45 | 46 | override fun initSimpleData(lists: MutableList): MutableList { 47 | lists.add("1.使用 runBlocking 顶层函数(常用于单元测试)") 48 | lists.add("2.使用 GlobalScope 单例对象(不推荐使用)") 49 | lists.add("3.通过 CoroutineContext 创建一个 CoroutineScope 对象(推荐使用)") 50 | lists.add("启动模式【CoroutineStart.LAZY】") 51 | return lists 52 | } 53 | 54 | init { 55 | lazyJob = mainScope.launch(start = CoroutineStart.LAZY) { 56 | val result = doCoroutines() 57 | Log.e(TAG, "${result},当前线程:${Thread.currentThread().name}") 58 | } 59 | } 60 | 61 | override fun onItemClick(position: Int) { 62 | when (position) { 63 | 0 -> { 64 | // 通常适用于单元测试的场景,而业务开发中不会用到这种方法,因为它是线程阻塞的 65 | runBlocking { 66 | launch { 67 | val result = doCoroutines() 68 | Log.e(TAG, "${result},当前线程:${Thread.currentThread().name}") 69 | } 70 | } 71 | } 72 | 1 -> { 73 | job = GlobalScope.launch { 74 | val result = doCoroutineScope() 75 | Log.e(TAG, "${result},当前线程:${Thread.currentThread().name}") 76 | } 77 | } 78 | 2 -> { 79 | // val jobScope = CoroutineScope(Job()) 80 | // val ioScope = CoroutineScope(Dispatchers.IO) 81 | // val nameScope = CoroutineScope(CoroutineName("TestName")) 82 | // val coroutineScope = CoroutineScope(Job() + Dispatchers.IO + CoroutineName("TestName")) 83 | mainScope.launch { 84 | val result = doCoroutines() 85 | Log.e(TAG, "${result},当前线程:${Thread.currentThread().name}") 86 | } 87 | } 88 | 3 -> { 89 | lazyJob?.start() 90 | } 91 | } 92 | } 93 | 94 | private suspend fun doCoroutines(): String { 95 | //暂停两秒,模拟耗时操作 96 | delay(1000L) 97 | Log.e(TAG, "doCoroutines完成, 当前线程:${Thread.currentThread().name}") 98 | return "成功执行doCoroutines" 99 | } 100 | 101 | private suspend fun doCoroutineScope() = coroutineScope { 102 | //暂停两秒,模拟耗时操作 103 | delay(1000L) 104 | withContext(Dispatchers.Main) { 105 | Log.e(TAG, "doCoroutineScope完成, 当前线程:${Thread.currentThread().name}") 106 | } 107 | "成功执行doCoroutineScope" 108 | } 109 | 110 | private suspend fun doSupervisorScope() = supervisorScope { 111 | //暂停两秒,模拟耗时操作 112 | delay(1000L) 113 | withContext(Dispatchers.Main) { 114 | Log.e(TAG, "doSupervisorScope完成, 当前线程:${Thread.currentThread().name}") 115 | } 116 | "成功执行doSupervisorScope" 117 | } 118 | 119 | override fun onDestroyView() { 120 | job?.cancel() 121 | lazyJob?.cancel() 122 | mainScope.cancel() 123 | super.onDestroyView() 124 | } 125 | 126 | } -------------------------------------------------------------------------------- /app/src/main/java/com/xuexiang/kotlinsample/fragment/coroutines/CoroutinesFlowFragment.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2022 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 | 18 | package com.xuexiang.kotlinsample.fragment.coroutines 19 | 20 | import android.util.Log 21 | import com.xuexiang.kotlinsample.core.BaseSimpleListFragment 22 | import com.xuexiang.xpage.annotation.Page 23 | import kotlinx.coroutines.* 24 | import kotlinx.coroutines.flow.* 25 | 26 | /** 27 | * flow 的代码块只有调用 collected() 才开始运行,正如 RxJava 创建的 Observables 只有调用 subscribe() 才开始运行一样。 28 | * 因此,flow必须在协程的环境下方可使用 29 | */ 30 | @Page(name = "协程Flow的使用") 31 | class CoroutinesFlowFragment : BaseSimpleListFragment() { 32 | 33 | private val TAG = "Coroutines-Flow" 34 | 35 | private val mainScope = MainScope() 36 | 37 | override fun initSimpleData(lists: MutableList): MutableList { 38 | lists.add("Flow简单使用") 39 | return lists 40 | } 41 | 42 | 43 | override fun onItemClick(position: Int) { 44 | when (position) { 45 | 0 -> { 46 | mainScope.launch { 47 | flowOf(1, 2, 3) 48 | .map { x -> 49 | x * 2 50 | } 51 | .filter { x -> x > 3 } 52 | .onEach { item -> 53 | Log.e(TAG, "on each: $item, 当前线程:${Thread.currentThread().name}") 54 | item + 1 55 | } 56 | .flowOn(Dispatchers.IO) 57 | .onCompletion { 58 | Log.e(TAG, "onCompletion, 当前线程:${Thread.currentThread().name}") 59 | }.collect { value -> 60 | Log.e(TAG, "collect: $value, 当前线程:${Thread.currentThread().name}") 61 | } 62 | } 63 | 64 | } 65 | 1 -> { 66 | 67 | } 68 | } 69 | } 70 | 71 | override fun onDestroyView() { 72 | mainScope.cancel() 73 | super.onDestroyView() 74 | } 75 | 76 | } -------------------------------------------------------------------------------- /app/src/main/java/com/xuexiang/kotlinsample/fragment/coroutines/CoroutinesXTaskFragment.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.fragment.coroutines 18 | 19 | import com.xuexiang.kotlinsample.core.BaseContainerFragment 20 | import com.xuexiang.kotlinsample.fragment.coroutines.business.ComplexBusinessFragment 21 | import com.xuexiang.kotlinsample.fragment.coroutines.concurrent.ConcurrentProcessFragment 22 | import com.xuexiang.xpage.annotation.Page 23 | 24 | /** 25 | * 协程使用 26 | * 27 | * @author xuexiang 28 | * @since 2022/3/25 1:42 上午 29 | */ 30 | @Page(name = "协程和XTask使用对比") 31 | class CoroutinesXTaskFragment : BaseContainerFragment() { 32 | 33 | override fun getPagesClasses(): Array> { 34 | return arrayOf( 35 | ComplexBusinessFragment::class.java, 36 | ConcurrentProcessFragment::class.java 37 | ) 38 | } 39 | } -------------------------------------------------------------------------------- /app/src/main/java/com/xuexiang/kotlinsample/fragment/coroutines/SchedulerChangeFragment.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2022 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 | 18 | package com.xuexiang.kotlinsample.fragment.coroutines 19 | 20 | import android.util.Log 21 | import com.xuexiang.kotlinsample.core.BaseSimpleListFragment 22 | import com.xuexiang.xpage.annotation.Page 23 | import kotlinx.coroutines.* 24 | 25 | /*** 26 | * 1.使用withContext进行线程串行切换 27 | * 2.使用async进行线程并行切换 28 | */ 29 | @Page(name = "协程线程切换") 30 | class SchedulerChangeFragment : BaseSimpleListFragment() { 31 | 32 | private val TAG = "Coroutines-Scheduler" 33 | 34 | private val mainScope = MainScope() 35 | 36 | override fun initSimpleData(lists: MutableList): MutableList { 37 | lists.add("1.使用withContext进行线程串行切换") 38 | lists.add("2.使用async进行线程并行切换") 39 | return lists 40 | } 41 | 42 | override fun onItemClick(position: Int) { 43 | when (position) { 44 | 0 -> { 45 | mainScope.launch { 46 | Log.e(TAG, "task start: ${Thread.currentThread().name}") 47 | val result = withContext(Dispatchers.IO) { 48 | delay(500) 49 | Log.e(TAG, "delay on: ${Thread.currentThread().name}") 50 | "task pass!" 51 | } 52 | Log.e(TAG, "task finished: ${Thread.currentThread().name}, result: $result") 53 | } 54 | } 55 | 1 -> { 56 | mainScope.launch { 57 | Log.e(TAG, "task start: ${Thread.currentThread().name}") 58 | val task1 = async { 59 | delay(100) 60 | Log.e(TAG, "subtask1 on: ${Thread.currentThread().name}") 61 | "subtask1 pass!" 62 | } 63 | val task2 = async(Dispatchers.IO) { 64 | delay(200) 65 | Log.e(TAG, "subtask2 on: ${Thread.currentThread().name}") 66 | "subtask2 pass!" 67 | } 68 | val task3 = async(Dispatchers.Default) { 69 | delay(300) 70 | Log.e(TAG, "subtask3 on: ${Thread.currentThread().name}") 71 | "subtask3 pass!" 72 | } 73 | Log.e( 74 | TAG, 75 | "task finished: ${Thread.currentThread().name}, result: ${task1.await()}-${task2.await()}-${task3.await()}" 76 | ) 77 | } 78 | } 79 | } 80 | } 81 | 82 | override fun onDestroyView() { 83 | mainScope.cancel() 84 | super.onDestroyView() 85 | } 86 | 87 | } -------------------------------------------------------------------------------- /app/src/main/java/com/xuexiang/kotlinsample/fragment/coroutines/business/entity/Product.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2022 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.fragment.coroutines.business.entity 18 | 19 | /** 20 | * 产品 21 | * 22 | * @author xuexiang 23 | * @since 2/25/22 1:17 AM 24 | */ 25 | class Product(var info: ProductInfo, var address: String) { 26 | 27 | var price: String? = null 28 | var publicTime: String? = null 29 | 30 | override fun toString(): String { 31 | return "产品信息:$info, 产地:$address, 价格:$price, 上市日前:$publicTime" 32 | } 33 | } -------------------------------------------------------------------------------- /app/src/main/java/com/xuexiang/kotlinsample/fragment/coroutines/business/entity/ProductFactory.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2022 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.fragment.coroutines.business.entity 18 | 19 | /** 20 | * 产品工厂 21 | * 22 | * @author xuexiang 23 | * @since 2/25/22 1:15 AM 24 | */ 25 | class ProductFactory(var id: String, var address: String) { 26 | 27 | fun produce(info: ProductInfo?): Product { 28 | return Product(info!!, address) 29 | } 30 | } -------------------------------------------------------------------------------- /app/src/main/java/com/xuexiang/kotlinsample/fragment/coroutines/business/entity/ProductInfo.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2022 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.fragment.coroutines.business.entity 18 | 19 | /** 20 | * 产品信息 21 | * 22 | * @author xuexiang 23 | * @since 2/25/22 12:40 AM 24 | */ 25 | class ProductInfo { 26 | /** 27 | * 编号 28 | */ 29 | var id: String 30 | 31 | /** 32 | * 品牌 33 | */ 34 | var brand: String? = null 35 | 36 | /** 37 | * 质量 38 | */ 39 | var quality: String? = null 40 | 41 | constructor(id: String) { 42 | this.id = id 43 | } 44 | 45 | constructor(id: String, brand: String?, quality: String?) { 46 | this.id = id 47 | this.brand = brand 48 | this.quality = quality 49 | } 50 | 51 | override fun toString(): String { 52 | return "id:$id, 品牌:$brand, 品质:$quality" 53 | } 54 | } -------------------------------------------------------------------------------- /app/src/main/java/com/xuexiang/kotlinsample/fragment/coroutines/business/processor/AbstractProcessor.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2022 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.fragment.coroutines.business.processor 18 | 19 | import com.xuexiang.xui.widget.textview.LoggerTextView 20 | 21 | /** 22 | * 抽象处理器 23 | * 24 | * @author xuexiang 25 | * @since 2/25/22 12:28 AM 26 | */ 27 | abstract class AbstractProcessor(private val mLogger: LoggerTextView?) { 28 | 29 | private var mCallback: IProcessorCallback? = null 30 | 31 | fun setProcessorCallback(callback: IProcessorCallback): AbstractProcessor { 32 | mCallback = callback 33 | return this 34 | } 35 | 36 | /** 37 | * 处理任务 38 | * 39 | * @return 返回的结果 40 | */ 41 | abstract fun process(): T 42 | 43 | fun log(logContent: String?) { 44 | mLogger?.logNormal(logContent) 45 | } 46 | 47 | fun onProcessSuccess(t: T) { 48 | mCallback?.onSuccess(t) 49 | } 50 | 51 | fun onProcessFailed(error: String?) { 52 | mCallback?.onFailed(error) 53 | } 54 | 55 | /** 56 | * 模拟执行 57 | * 58 | * @param time 模拟执行所需要的时间 59 | */ 60 | fun mockProcess(time: Long) { 61 | try { 62 | Thread.sleep(time) 63 | } catch (e: InterruptedException) { 64 | e.printStackTrace() 65 | } 66 | } 67 | 68 | abstract class ProcessorCallbackAdapter : IProcessorCallback { 69 | override fun onFailed(error: String?) {} 70 | } 71 | 72 | interface IProcessorCallback { 73 | /** 74 | * 处理成功 75 | * 76 | * @param result 结果 77 | */ 78 | fun onSuccess(result: T) 79 | 80 | /** 81 | * 处理失败 82 | * 83 | * @param error 错误信息 84 | */ 85 | fun onFailed(error: String?) 86 | } 87 | } -------------------------------------------------------------------------------- /app/src/main/java/com/xuexiang/kotlinsample/fragment/coroutines/business/processor/GetProductInfoProcessor.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2022 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.fragment.coroutines.business.processor 18 | 19 | import com.xuexiang.kotlinsample.fragment.coroutines.business.entity.ProductInfo 20 | import com.xuexiang.xui.widget.textview.LoggerTextView 21 | 22 | /** 23 | * 1.获取产品信息 24 | * 25 | * @author xuexiang 26 | * @since 2/25/22 12:34 AM 27 | */ 28 | class GetProductInfoProcessor(logger: LoggerTextView?, private val id: String) : 29 | AbstractProcessor(logger) { 30 | 31 | override fun process(): ProductInfo { 32 | log("[获取产品信息]开始执行...") 33 | val info = getProductInfoById(id) 34 | log("[获取产品信息]执行完毕!") 35 | onProcessSuccess(info) 36 | return info 37 | } 38 | 39 | private fun getProductInfoById(id: String): ProductInfo { 40 | // 模拟耗费的时间 41 | mockProcess(500) 42 | return ProductInfo(id, "品牌A", "高品质") 43 | } 44 | } -------------------------------------------------------------------------------- /app/src/main/java/com/xuexiang/kotlinsample/fragment/coroutines/business/processor/GivePriceProcessor.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2022 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.fragment.coroutines.business.processor 18 | 19 | import com.xuexiang.kotlinsample.fragment.coroutines.business.entity.Product 20 | import com.xuexiang.xui.widget.textview.LoggerTextView 21 | 22 | /** 23 | * 3.评估产品,给出价格 24 | * @author xuexiang 25 | * @since 2/25/22 1:36 AM 26 | */ 27 | class GivePriceProcessor(logger: LoggerTextView?, private val product: Product) : 28 | AbstractProcessor(logger) { 29 | override fun process(): Product { 30 | log("[评估产品价格]开始执行...") 31 | val price = givePrice(product) 32 | product.price = price 33 | log("[评估产品价格]执行完毕!") 34 | onProcessSuccess(product) 35 | return product 36 | } 37 | 38 | private fun givePrice(product: Product): String { 39 | // 模拟耗费的时间 40 | mockProcess(100) 41 | return "45¥" 42 | } 43 | } -------------------------------------------------------------------------------- /app/src/main/java/com/xuexiang/kotlinsample/fragment/coroutines/business/processor/PublicProductProcessor.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2022 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.fragment.coroutines.business.processor 18 | 19 | import com.xuexiang.kotlinsample.fragment.coroutines.business.entity.Product 20 | import com.xuexiang.xui.widget.textview.LoggerTextView 21 | 22 | /** 23 | * 4.产品发布 24 | * 25 | * @author xuexiang 26 | * @since 2/25/22 1:50 AM 27 | */ 28 | class PublicProductProcessor : AbstractProcessor { 29 | private var product: Product? = null 30 | 31 | constructor(logger: LoggerTextView?, product: Product?) : super(logger) { 32 | this.product = product 33 | } 34 | 35 | constructor(logger: LoggerTextView?) : super(logger) 36 | 37 | override fun process(): Product { 38 | log("[产品发布]开始执行...") 39 | val time = getPublicPlan(product) 40 | product!!.publicTime = time 41 | log("[产品发布]执行完毕!") 42 | onProcessSuccess(product) 43 | return product!! 44 | } 45 | 46 | private fun getPublicPlan(product: Product?): String { 47 | // 模拟耗费的时间 48 | mockProcess(400) 49 | return "2022年2月22日22时22分22秒" 50 | } 51 | } -------------------------------------------------------------------------------- /app/src/main/java/com/xuexiang/kotlinsample/fragment/coroutines/business/processor/SearchFactoryProcessor.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2022 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.fragment.coroutines.business.processor 18 | 19 | import com.xuexiang.kotlinsample.fragment.coroutines.business.entity.ProductFactory 20 | import com.xuexiang.kotlinsample.fragment.coroutines.business.entity.ProductInfo 21 | import com.xuexiang.xui.widget.textview.LoggerTextView 22 | 23 | /** 24 | * 2.查找相关的工厂 25 | * 26 | * @author xuexiang 27 | * @since 2/25/22 1:13 AM 28 | */ 29 | class SearchFactoryProcessor(logger: LoggerTextView?, private val info: ProductInfo) : 30 | AbstractProcessor(logger) { 31 | override fun process(): ProductFactory { 32 | log("[查找相关工厂]开始执行...") 33 | val factory = searchFactoryByBrand(info.brand) 34 | log("[查找相关工厂]执行完毕!") 35 | onProcessSuccess(factory) 36 | return factory 37 | } 38 | 39 | private fun searchFactoryByBrand(brand: String?): ProductFactory { 40 | // 模拟耗费的时间 41 | mockProcess(300) 42 | return ProductFactory(brand!!, "南京市江宁区秣陵街道xxx街区") 43 | } 44 | } -------------------------------------------------------------------------------- /app/src/main/java/com/xuexiang/kotlinsample/fragment/coroutines/business/task/AbstractTask.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2022 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.fragment.coroutines.business.task 18 | 19 | import com.xuexiang.xui.widget.textview.LoggerTextView 20 | import com.xuexiang.xtask.api.step.SimpleTaskStep 21 | 22 | /** 23 | * 基础抽象任务 24 | * 25 | * @author xuexiang 26 | * @since 2/25/22 2:18 AM 27 | */ 28 | abstract class AbstractTask(var mLogger: LoggerTextView?) : SimpleTaskStep() { 29 | fun log(logContent: String?) { 30 | if (mLogger != null) { 31 | mLogger!!.logSuccess(logContent) 32 | } 33 | } 34 | 35 | override fun isAutoNotify(): Boolean { 36 | // 这里进行手动控制 37 | return false 38 | } 39 | } -------------------------------------------------------------------------------- /app/src/main/java/com/xuexiang/kotlinsample/fragment/coroutines/business/task/GetProductInfoTask.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2022 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.fragment.coroutines.business.task 18 | 19 | import com.xuexiang.kotlinsample.fragment.coroutines.business.entity.ProductInfo 20 | import com.xuexiang.kotlinsample.fragment.coroutines.business.processor.AbstractProcessor 21 | import com.xuexiang.kotlinsample.fragment.coroutines.business.processor.GetProductInfoProcessor 22 | import com.xuexiang.xtask.core.param.ITaskResult 23 | import com.xuexiang.xui.widget.textview.LoggerTextView 24 | 25 | /** 26 | * 1.获取产品信息 27 | * 28 | * @author xuexiang 29 | * @since 2/25/22 2:07 AM 30 | */ 31 | class GetProductInfoTask(logger: LoggerTextView?) : AbstractTask(logger) { 32 | @Throws(Exception::class) 33 | override fun doTask() { 34 | val productId = taskParam.getString(ProductTaskConstants.KEY_PRODUCT_ID) 35 | GetProductInfoProcessor(mLogger, productId) 36 | .setProcessorCallback(object : AbstractProcessor.IProcessorCallback { 37 | override fun onSuccess(info: ProductInfo?) { 38 | taskParam.put(ProductTaskConstants.KEY_PRODUCT_INFO, info) 39 | notifyTaskSucceed() 40 | } 41 | 42 | override fun onFailed(error: String?) { 43 | notifyTaskFailed(ITaskResult.ERROR, error) 44 | } 45 | }).process() 46 | } 47 | 48 | override fun getName(): String { 49 | return "1.获取产品信息" 50 | } 51 | } -------------------------------------------------------------------------------- /app/src/main/java/com/xuexiang/kotlinsample/fragment/coroutines/business/task/GivePriceTask.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2022 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.fragment.coroutines.business.task 18 | 19 | import com.xuexiang.kotlinsample.fragment.coroutines.business.entity.Product 20 | import com.xuexiang.kotlinsample.fragment.coroutines.business.processor.AbstractProcessor 21 | import com.xuexiang.kotlinsample.fragment.coroutines.business.processor.GivePriceProcessor 22 | import com.xuexiang.xtask.core.param.ITaskResult 23 | import com.xuexiang.xui.widget.textview.LoggerTextView 24 | 25 | /** 26 | * 3.评估产品,给出价格 27 | * 28 | * @author xuexiang 29 | * @since 2/25/22 2:27 AM 30 | */ 31 | class GivePriceTask(logger: LoggerTextView?) : AbstractTask(logger) { 32 | 33 | @Throws(Exception::class) 34 | override fun doTask() { 35 | 36 | val product: Product = 37 | taskParam.getObject(ProductTaskConstants.KEY_PRODUCT, Product::class.java) 38 | 39 | GivePriceProcessor(mLogger, product).setProcessorCallback(object : 40 | AbstractProcessor.IProcessorCallback { 41 | override fun onSuccess(result: Product?) { 42 | taskParam.put(ProductTaskConstants.KEY_PRODUCT, result) 43 | notifyTaskSucceed() 44 | } 45 | 46 | override fun onFailed(error: String?) { 47 | notifyTaskFailed(ITaskResult.ERROR, error) 48 | } 49 | }).process() 50 | } 51 | 52 | override fun getName(): String { 53 | return "3.评估产品,给出价格" 54 | } 55 | } -------------------------------------------------------------------------------- /app/src/main/java/com/xuexiang/kotlinsample/fragment/coroutines/business/task/ProductTaskConstants.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2022 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.fragment.coroutines.business.task 18 | 19 | /** 20 | * @author xuexiang 21 | * @since 2/25/22 2:14 AM 22 | */ 23 | object ProductTaskConstants { 24 | const val KEY_PRODUCT_ID = "key_product_id" 25 | const val KEY_PRODUCT_INFO = "key_product_info" 26 | const val KEY_PRODUCT = "key_product" 27 | } -------------------------------------------------------------------------------- /app/src/main/java/com/xuexiang/kotlinsample/fragment/coroutines/business/task/PublicProductTask.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2022 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.fragment.coroutines.business.task 18 | 19 | import com.xuexiang.kotlinsample.fragment.coroutines.business.entity.Product 20 | import com.xuexiang.kotlinsample.fragment.coroutines.business.processor.AbstractProcessor 21 | import com.xuexiang.kotlinsample.fragment.coroutines.business.processor.PublicProductProcessor 22 | import com.xuexiang.xtask.core.param.ITaskResult 23 | import com.xuexiang.xui.widget.textview.LoggerTextView 24 | 25 | /** 26 | * 4.产品发布 27 | * 28 | * @author xuexiang 29 | * @since 2/25/22 2:31 AM 30 | */ 31 | class PublicProductTask(logger: LoggerTextView?) : AbstractTask(logger) { 32 | @Throws(Exception::class) 33 | override fun doTask() { 34 | val product: Product = 35 | taskParam.getObject(ProductTaskConstants.KEY_PRODUCT, Product::class.java) 36 | 37 | PublicProductProcessor(mLogger, product).setProcessorCallback(object : 38 | AbstractProcessor.IProcessorCallback { 39 | override fun onSuccess(result: Product?) { 40 | taskParam.put(ProductTaskConstants.KEY_PRODUCT, result) 41 | notifyTaskSucceed() 42 | } 43 | 44 | override fun onFailed(error: String?) { 45 | notifyTaskFailed(ITaskResult.ERROR, error) 46 | } 47 | }).process() 48 | } 49 | 50 | override fun getName(): String { 51 | return "4.产品发布" 52 | } 53 | } -------------------------------------------------------------------------------- /app/src/main/java/com/xuexiang/kotlinsample/fragment/coroutines/business/task/SearchFactoryTask.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2022 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.fragment.coroutines.business.task 18 | 19 | import com.xuexiang.kotlinsample.fragment.coroutines.business.entity.Product 20 | import com.xuexiang.kotlinsample.fragment.coroutines.business.entity.ProductFactory 21 | import com.xuexiang.kotlinsample.fragment.coroutines.business.entity.ProductInfo 22 | import com.xuexiang.kotlinsample.fragment.coroutines.business.processor.AbstractProcessor 23 | import com.xuexiang.kotlinsample.fragment.coroutines.business.processor.SearchFactoryProcessor 24 | import com.xuexiang.xtask.core.param.ITaskResult 25 | import com.xuexiang.xui.widget.textview.LoggerTextView 26 | 27 | /** 28 | * 2.查找相关的工厂并生产 29 | * 30 | * @author xuexiang 31 | * @since 2/25/22 2:17 AM 32 | */ 33 | class SearchFactoryTask(logger: LoggerTextView?) : AbstractTask(logger) { 34 | 35 | @Throws(Exception::class) 36 | override fun doTask() { 37 | val productInfo: ProductInfo = taskParam.getObject( 38 | ProductTaskConstants.KEY_PRODUCT_INFO, 39 | ProductInfo::class.java 40 | ) 41 | SearchFactoryProcessor(mLogger, productInfo) 42 | .setProcessorCallback(object : AbstractProcessor.IProcessorCallback { 43 | override fun onSuccess(factory: ProductFactory?) { 44 | log("开始生产产品...") 45 | val product: Product? = factory?.produce(productInfo) 46 | taskParam.put(ProductTaskConstants.KEY_PRODUCT, product) 47 | notifyTaskSucceed() 48 | } 49 | 50 | override fun onFailed(error: String?) { 51 | notifyTaskFailed(ITaskResult.ERROR, error) 52 | } 53 | }) 54 | .process() 55 | } 56 | 57 | override fun getName(): String { 58 | return "2.查找相关的工厂并生产" 59 | } 60 | } -------------------------------------------------------------------------------- /app/src/main/java/com/xuexiang/kotlinsample/fragment/coroutines/concurrent/entity/BriefInfo.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2022 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.fragment.coroutines.concurrent.entity 18 | 19 | /** 20 | * 产品简要信息 21 | * 22 | * @author xuexiang 23 | * @since 3/22/22 1:08 AM 24 | */ 25 | open class BriefInfo { 26 | var id: String 27 | var name: String? = null 28 | var factoryId: String? = null 29 | var priceId: String? = null 30 | var promotionId: String? = null 31 | var richId: String? = null 32 | 33 | constructor(id: String) { 34 | this.id = id 35 | } 36 | 37 | constructor(briefInfo: BriefInfo) : this( 38 | briefInfo.id, 39 | briefInfo.name, 40 | briefInfo.factoryId, 41 | briefInfo.priceId, 42 | briefInfo.promotionId, 43 | briefInfo.richId 44 | ) 45 | 46 | constructor( 47 | id: String, 48 | name: String?, 49 | factoryId: String?, 50 | priceId: String?, 51 | promotionId: String?, 52 | richId: String? 53 | ) { 54 | this.id = id 55 | this.name = name 56 | this.factoryId = factoryId 57 | this.priceId = priceId 58 | this.promotionId = promotionId 59 | this.richId = richId 60 | } 61 | } -------------------------------------------------------------------------------- /app/src/main/java/com/xuexiang/kotlinsample/fragment/coroutines/concurrent/entity/FactoryInfo.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2022 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.fragment.coroutines.concurrent.entity 18 | 19 | /** 20 | * 工厂生产信息 21 | * 22 | * @author xuexiang 23 | * @since 3/22/22 1:11 AM 24 | */ 25 | class FactoryInfo(var id: String) { 26 | /** 27 | * 生产地址 28 | */ 29 | var address: String? = null 30 | 31 | /** 32 | * 生产日期 33 | */ 34 | var productDate: String? = null 35 | 36 | /** 37 | * 过期日期 38 | */ 39 | var expirationDate: String? = null 40 | 41 | override fun toString(): String { 42 | return ("生产编号:" + id 43 | + ", 生产地址:" + address 44 | + ", 生产日期:" + productDate 45 | + ", 过期日期:" + expirationDate) 46 | } 47 | } -------------------------------------------------------------------------------- /app/src/main/java/com/xuexiang/kotlinsample/fragment/coroutines/concurrent/entity/PriceInfo.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2022 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.fragment.coroutines.concurrent.entity 18 | 19 | import com.xuexiang.kotlinsample.fragment.coroutines.concurrent.entity.PriceInfo 20 | 21 | /** 22 | * 价格信息 23 | * 24 | * @author xuexiang 25 | * @since 3/22/22 1:10 AM 26 | */ 27 | class PriceInfo(var id: String) { 28 | /** 29 | * 出厂价 30 | */ 31 | var factoryPrice = 0f 32 | /** 33 | * 批发价 34 | */ 35 | var wholesalePrice = 0f 36 | /** 37 | * 零售价 38 | */ 39 | var retailPrice = 0f 40 | 41 | override fun toString(): String { 42 | return ("价格编号:" + id 43 | + ", 出厂价:" + factoryPrice 44 | + ", 批发价:" + wholesalePrice 45 | + ", 零售价:" + retailPrice) 46 | } 47 | } -------------------------------------------------------------------------------- /app/src/main/java/com/xuexiang/kotlinsample/fragment/coroutines/concurrent/entity/Product.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2022 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.fragment.coroutines.concurrent.entity 18 | 19 | /** 20 | * 产品 21 | * 22 | * @author xuexiang 23 | * @since 3/22/22 1:07 AM 24 | */ 25 | class Product(briefInfo: BriefInfo) : BriefInfo(briefInfo) { 26 | /** 27 | * 生产信息 28 | */ 29 | var factory: FactoryInfo? = null 30 | /** 31 | * 价格信息 32 | */ 33 | var price: PriceInfo? = null 34 | /** 35 | * 促销信息 36 | */ 37 | var promotion: PromotionInfo? = null 38 | /** 39 | * 富文本信息 40 | */ 41 | var rich: RichInfo? = null 42 | 43 | 44 | override fun toString(): String { 45 | return """ 46 | 产品信息: $name 47 | 产地信息: $factory 48 | 价格信息: $price 49 | 促销信息: $promotion 50 | 富文本信息: $rich 51 | """.trimIndent() 52 | } 53 | } -------------------------------------------------------------------------------- /app/src/main/java/com/xuexiang/kotlinsample/fragment/coroutines/concurrent/entity/PromotionInfo.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2022 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.fragment.coroutines.concurrent.entity 18 | 19 | /** 20 | * 产品促销信息 21 | * 22 | * @author xuexiang 23 | * @since 3/22/22 1:12 AM 24 | */ 25 | class PromotionInfo(var id: String) { 26 | /** 27 | * 促销类型 28 | */ 29 | var type = 0 30 | /** 31 | * 促销内容 32 | */ 33 | var content: String? = null 34 | /** 35 | * 生效日期 36 | */ 37 | var effectiveDate: String? = null 38 | /** 39 | * 失效日期 40 | */ 41 | var expirationDate: String? = null 42 | 43 | override fun toString(): String { 44 | return ("促销编号:" + id 45 | + ", 促销类型:" + type 46 | + ", 促销内容:" + content 47 | + ", 生效日期:" + effectiveDate 48 | + ", 失效日期:" + expirationDate) 49 | } 50 | } -------------------------------------------------------------------------------- /app/src/main/java/com/xuexiang/kotlinsample/fragment/coroutines/concurrent/entity/RichInfo.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2022 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.fragment.coroutines.concurrent.entity 18 | 19 | /** 20 | * 富文本信息 21 | * 22 | * @author xuexiang 23 | * @since 3/22/22 1:13 AM 24 | */ 25 | class RichInfo(var id: String) { 26 | /** 27 | * 描述信息 28 | */ 29 | var description: String? = null 30 | /** 31 | * 图片链接 32 | */ 33 | var imgUrl: String? = null 34 | /** 35 | * 视频链接 36 | */ 37 | var videoUrl: String? = null 38 | 39 | override fun toString(): String { 40 | return ("富文本编号:" + id 41 | + ", 描述信息:" + description 42 | + ", 图片链接:" + imgUrl 43 | + ", 视频链接:" + videoUrl) 44 | } 45 | } -------------------------------------------------------------------------------- /app/src/main/java/com/xuexiang/kotlinsample/fragment/coroutines/concurrent/processor/GetBriefInfoProcessor.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2022 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.fragment.coroutines.concurrent.processor 18 | 19 | import com.xuexiang.kotlinsample.fragment.coroutines.business.processor.AbstractProcessor 20 | import com.xuexiang.kotlinsample.fragment.coroutines.concurrent.entity.BriefInfo 21 | import com.xuexiang.xui.widget.textview.LoggerTextView 22 | 23 | /** 24 | * 1 获取商品简要信息 25 | * 26 | * @author xuexiang 27 | * @since 3/22/22 1:18 AM 28 | */ 29 | class GetBriefInfoProcessor(logger: LoggerTextView?, private val productId: String) : 30 | AbstractProcessor(logger) { 31 | override fun process(): BriefInfo { 32 | log("[简要信息查询]开始执行...") 33 | val info = getBriefInfoById(productId) 34 | log("[简要信息查询]执行完毕!") 35 | onProcessSuccess(info) 36 | return info 37 | } 38 | 39 | private fun getBriefInfoById(id: String): BriefInfo { 40 | // 模拟耗费的时间 41 | mockProcess(500) 42 | return BriefInfo(id).apply { 43 | name = "统一老坛酸菜牛肉面" 44 | factoryId = "fa234632-1234-4567" 45 | priceId = "pr432359-3745-9426" 46 | promotionId = "pt235123-9654-2942" 47 | richId = "ri735294-2346-1048" 48 | } 49 | } 50 | } -------------------------------------------------------------------------------- /app/src/main/java/com/xuexiang/kotlinsample/fragment/coroutines/concurrent/processor/GetFactoryInfoProcessor.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2022 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.fragment.coroutines.concurrent.processor 18 | 19 | import com.xuexiang.kotlinsample.fragment.coroutines.business.processor.AbstractProcessor 20 | import com.xuexiang.kotlinsample.fragment.coroutines.concurrent.entity.FactoryInfo 21 | import com.xuexiang.xui.widget.textview.LoggerTextView 22 | 23 | /** 24 | * 2.1 获取商品的生产信息 25 | * 26 | * @author xuexiang 27 | * @since 3/22/22 1:22 AM 28 | */ 29 | class GetFactoryInfoProcessor(logger: LoggerTextView?, private val factoryId: String) : 30 | AbstractProcessor(logger) { 31 | override fun process(): FactoryInfo { 32 | log("[生产信息查询]开始执行...") 33 | val info = getFactoryInfoById( 34 | factoryId 35 | ) 36 | log("[生产信息查询]执行完毕!") 37 | onProcessSuccess(info) 38 | return info 39 | } 40 | 41 | private fun getFactoryInfoById(id: String): FactoryInfo { 42 | // 模拟耗费的时间 43 | mockProcess(200) 44 | return FactoryInfo(id).apply { 45 | address = "长沙市开福区金霞经济开发区中青路1301号长沙统一企业有限公司" 46 | productDate = "2022年3月15日" 47 | expirationDate = "2030年3月15日" 48 | } 49 | } 50 | } -------------------------------------------------------------------------------- /app/src/main/java/com/xuexiang/kotlinsample/fragment/coroutines/concurrent/processor/GetPriceInfoProcessor.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2022 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.fragment.coroutines.concurrent.processor 18 | 19 | import com.xuexiang.kotlinsample.fragment.coroutines.business.processor.AbstractProcessor 20 | import com.xuexiang.kotlinsample.fragment.coroutines.concurrent.entity.PriceInfo 21 | import com.xuexiang.xui.widget.textview.LoggerTextView 22 | 23 | /** 24 | * 2.2 获取商品的价格信息 25 | * 26 | * @author xuexiang 27 | * @since 3/22/22 1:20 AM 28 | */ 29 | class GetPriceInfoProcessor(logger: LoggerTextView?, private val priceId: String) : 30 | AbstractProcessor(logger) { 31 | override fun process(): PriceInfo { 32 | log("[价格信息查询]开始执行...") 33 | val info: PriceInfo = getPriceInfoById(priceId) 34 | log("[价格信息查询]执行完毕!") 35 | onProcessSuccess(info) 36 | return info 37 | } 38 | 39 | private fun getPriceInfoById(id: String): PriceInfo { 40 | // 模拟耗费的时间 41 | mockProcess(300) 42 | return PriceInfo(id).apply { 43 | factoryPrice = 1.5f 44 | wholesalePrice = 2.5f 45 | retailPrice = 4.5f 46 | } 47 | } 48 | } -------------------------------------------------------------------------------- /app/src/main/java/com/xuexiang/kotlinsample/fragment/coroutines/concurrent/processor/GetPromotionInfoProcessor.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2022 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.fragment.coroutines.concurrent.processor 18 | 19 | import com.xuexiang.kotlinsample.fragment.coroutines.business.processor.AbstractProcessor 20 | import com.xuexiang.kotlinsample.fragment.coroutines.concurrent.entity.PromotionInfo 21 | import com.xuexiang.xui.widget.textview.LoggerTextView 22 | 23 | /** 24 | * 2.3 获取商品的促销信息 25 | * 26 | * @author xuexiang 27 | * @since 3/22/22 1:23 AM 28 | */ 29 | class GetPromotionInfoProcessor(logger: LoggerTextView?, private val promotionId: String) : 30 | AbstractProcessor(logger) { 31 | override fun process(): PromotionInfo { 32 | log("[促销信息查询]开始执行...") 33 | val info: PromotionInfo = getPromotionInfoById(promotionId) 34 | log("[促销信息查询]执行完毕!") 35 | onProcessSuccess(info) 36 | return info 37 | } 38 | 39 | private fun getPromotionInfoById(id: String): PromotionInfo { 40 | // 模拟耗费的时间 41 | mockProcess(150) 42 | return PromotionInfo(id).apply { 43 | type = 5 44 | content = "买一送一" 45 | effectiveDate = "2022年3月15日" 46 | expirationDate = "2022年4月15日" 47 | } 48 | } 49 | } -------------------------------------------------------------------------------- /app/src/main/java/com/xuexiang/kotlinsample/fragment/coroutines/concurrent/processor/GetRichInfoProcessor.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2022 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.fragment.coroutines.concurrent.processor 18 | 19 | import com.xuexiang.kotlinsample.fragment.coroutines.business.processor.AbstractProcessor 20 | import com.xuexiang.kotlinsample.fragment.coroutines.concurrent.entity.RichInfo 21 | import com.xuexiang.xui.widget.textview.LoggerTextView 22 | 23 | /** 24 | * 2.4 获取商品的富文本信息 25 | * 26 | * @author xuexiang 27 | * @since 3/22/22 1:21 AM 28 | */ 29 | class GetRichInfoProcessor(logger: LoggerTextView?, private val richId: String) : 30 | AbstractProcessor(logger) { 31 | override fun process(): RichInfo { 32 | log("[富文本信息查询]开始执行...") 33 | val info: RichInfo = getRichInfoById(richId) 34 | log("[富文本信息查询]执行完毕!") 35 | onProcessSuccess(info) 36 | return info 37 | } 38 | 39 | private fun getRichInfoById(id: String): RichInfo { 40 | // 模拟耗费的时间 41 | mockProcess(380) 42 | return RichInfo(id).apply { 43 | description = "精选湖南插旗菜业古法土坑腌制,取上乘泡脚酸菜,让你尽享人间美味!" 44 | imgUrl = "http://inews.gtimg.com/newsapp_bt/0/14650183855/641" 45 | videoUrl = "https://haokan.baidu.com/v?pd=wisenatural&vid=8687875510146074163" 46 | } 47 | } 48 | } -------------------------------------------------------------------------------- /app/src/main/java/com/xuexiang/kotlinsample/fragment/coroutines/concurrent/task/GetBriefInfoTask.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2022 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.fragment.coroutines.concurrent.task 18 | 19 | import com.xuexiang.kotlinsample.fragment.coroutines.business.processor.AbstractProcessor 20 | import com.xuexiang.kotlinsample.fragment.coroutines.business.task.AbstractTask 21 | import com.xuexiang.kotlinsample.fragment.coroutines.business.task.ProductTaskConstants 22 | import com.xuexiang.kotlinsample.fragment.coroutines.concurrent.entity.BriefInfo 23 | import com.xuexiang.kotlinsample.fragment.coroutines.concurrent.entity.Product 24 | import com.xuexiang.kotlinsample.fragment.coroutines.concurrent.processor.GetBriefInfoProcessor 25 | import com.xuexiang.xtask.core.param.ITaskResult 26 | import com.xuexiang.xui.widget.textview.LoggerTextView 27 | 28 | /** 29 | * 获取商品简要信息 30 | * 31 | * @author xuexiang 32 | * @since 3/22/22 11:52 PM 33 | */ 34 | class GetBriefInfoTask(logger: LoggerTextView?) : AbstractTask(logger) { 35 | 36 | @Throws(Exception::class) 37 | override fun doTask() { 38 | val productId = taskParam.getString(ProductTaskConstants.KEY_PRODUCT_ID) 39 | GetBriefInfoProcessor(mLogger, productId) 40 | .setProcessorCallback(object : AbstractProcessor.IProcessorCallback { 41 | override fun onSuccess(briefInfo: BriefInfo?) { 42 | val product = Product(briefInfo!!) 43 | taskParam.put(ProductTaskConstants.KEY_PRODUCT, product) 44 | notifyTaskSucceed() 45 | } 46 | 47 | override fun onFailed(error: String?) { 48 | notifyTaskFailed(ITaskResult.ERROR, error) 49 | } 50 | }) 51 | .process() 52 | } 53 | 54 | override fun getName(): String { 55 | return "1.获取商品简要信息" 56 | } 57 | } -------------------------------------------------------------------------------- /app/src/main/java/com/xuexiang/kotlinsample/fragment/coroutines/concurrent/task/GetFactoryInfoTask.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2022 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.fragment.coroutines.concurrent.task 18 | 19 | import com.xuexiang.kotlinsample.fragment.coroutines.business.processor.AbstractProcessor 20 | import com.xuexiang.kotlinsample.fragment.coroutines.business.task.AbstractTask 21 | import com.xuexiang.kotlinsample.fragment.coroutines.business.task.ProductTaskConstants 22 | import com.xuexiang.kotlinsample.fragment.coroutines.concurrent.entity.FactoryInfo 23 | import com.xuexiang.kotlinsample.fragment.coroutines.concurrent.entity.Product 24 | import com.xuexiang.kotlinsample.fragment.coroutines.concurrent.processor.GetFactoryInfoProcessor 25 | import com.xuexiang.xtask.core.param.ITaskResult 26 | import com.xuexiang.xui.widget.textview.LoggerTextView 27 | import com.xuexiang.xutil.common.StringUtils 28 | 29 | /** 30 | * 2.1 获取商品的生产信息 31 | * 32 | * @author xuexiang 33 | * @since 3/23/22 12:18 AM 34 | */ 35 | class GetFactoryInfoTask(logger: LoggerTextView?) : AbstractTask(logger) { 36 | @Throws(Exception::class) 37 | override fun doTask() { 38 | val product: Product? = taskParam.getObject(ProductTaskConstants.KEY_PRODUCT, Product::class.java) 39 | if (product == null || StringUtils.isEmpty(product.factoryId)) { 40 | notifyTaskFailed(ITaskResult.ERROR, "product is null or factoryId is empty!") 41 | return 42 | } 43 | GetFactoryInfoProcessor(mLogger, product.factoryId!!) 44 | .setProcessorCallback(object : AbstractProcessor.IProcessorCallback { 45 | override fun onSuccess(factoryInfo: FactoryInfo?) { 46 | taskParam.put( 47 | ProductTaskConstants.KEY_PRODUCT, 48 | product.apply { factory = factoryInfo } 49 | ) 50 | notifyTaskSucceed() 51 | } 52 | 53 | override fun onFailed(error: String?) { 54 | notifyTaskFailed(ITaskResult.ERROR, error) 55 | } 56 | }) 57 | .process() 58 | } 59 | 60 | override fun getName(): String { 61 | return "2.1 获取商品的生产信息" 62 | } 63 | } -------------------------------------------------------------------------------- /app/src/main/java/com/xuexiang/kotlinsample/fragment/coroutines/concurrent/task/GetPriceInfoTask.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2022 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.fragment.coroutines.concurrent.task 18 | 19 | import com.xuexiang.kotlinsample.fragment.coroutines.business.processor.AbstractProcessor 20 | import com.xuexiang.kotlinsample.fragment.coroutines.business.task.AbstractTask 21 | import com.xuexiang.kotlinsample.fragment.coroutines.business.task.ProductTaskConstants 22 | import com.xuexiang.kotlinsample.fragment.coroutines.concurrent.entity.PriceInfo 23 | import com.xuexiang.kotlinsample.fragment.coroutines.concurrent.entity.Product 24 | import com.xuexiang.kotlinsample.fragment.coroutines.concurrent.processor.GetPriceInfoProcessor 25 | import com.xuexiang.xtask.core.param.ITaskResult 26 | import com.xuexiang.xui.widget.textview.LoggerTextView 27 | import com.xuexiang.xutil.common.StringUtils 28 | 29 | /** 30 | * 2.2 获取商品的价格信息 31 | * 32 | * @author xuexiang 33 | * @since 3/23/22 12:18 AM 34 | */ 35 | class GetPriceInfoTask(logger: LoggerTextView?) : AbstractTask(logger) { 36 | @Throws(Exception::class) 37 | override fun doTask() { 38 | val product: Product? = 39 | taskParam.getObject(ProductTaskConstants.KEY_PRODUCT, Product::class.java) 40 | if (product == null || StringUtils.isEmpty(product.priceId)) { 41 | notifyTaskFailed(ITaskResult.ERROR, "product is null or priceId is empty!") 42 | return 43 | } 44 | GetPriceInfoProcessor(mLogger, product.priceId!!) 45 | .setProcessorCallback(object : AbstractProcessor.IProcessorCallback { 46 | override fun onSuccess(priceInfo: PriceInfo?) { 47 | taskParam.put( 48 | ProductTaskConstants.KEY_PRODUCT, 49 | product.apply { price = priceInfo }) 50 | notifyTaskSucceed() 51 | } 52 | 53 | override fun onFailed(error: String?) { 54 | notifyTaskFailed(ITaskResult.ERROR, error) 55 | } 56 | }) 57 | .process() 58 | } 59 | 60 | override fun getName(): String { 61 | return "2.2 获取商品的价格信息" 62 | } 63 | } -------------------------------------------------------------------------------- /app/src/main/java/com/xuexiang/kotlinsample/fragment/coroutines/concurrent/task/GetPromotionInfoTask.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2022 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.fragment.coroutines.concurrent.task 18 | 19 | import com.xuexiang.kotlinsample.fragment.coroutines.business.processor.AbstractProcessor 20 | import com.xuexiang.kotlinsample.fragment.coroutines.business.task.AbstractTask 21 | import com.xuexiang.kotlinsample.fragment.coroutines.business.task.ProductTaskConstants 22 | import com.xuexiang.kotlinsample.fragment.coroutines.concurrent.entity.Product 23 | import com.xuexiang.kotlinsample.fragment.coroutines.concurrent.entity.PromotionInfo 24 | import com.xuexiang.kotlinsample.fragment.coroutines.concurrent.processor.GetPromotionInfoProcessor 25 | import com.xuexiang.xtask.core.param.ITaskResult 26 | import com.xuexiang.xui.widget.textview.LoggerTextView 27 | import com.xuexiang.xutil.common.StringUtils 28 | 29 | /** 30 | * 2.3 获取商品的促销信息 31 | * 32 | * @author xuexiang 33 | * @since 3/23/22 12:18 AM 34 | */ 35 | class GetPromotionInfoTask(logger: LoggerTextView?) : AbstractTask(logger) { 36 | @Throws(Exception::class) 37 | override fun doTask() { 38 | val product: Product? = 39 | taskParam.getObject(ProductTaskConstants.KEY_PRODUCT, Product::class.java) 40 | if (product == null || StringUtils.isEmpty(product.promotionId)) { 41 | notifyTaskFailed(ITaskResult.ERROR, "product is null or promotionId is empty!") 42 | return 43 | } 44 | GetPromotionInfoProcessor(mLogger, product.promotionId!!) 45 | .setProcessorCallback(object : AbstractProcessor.IProcessorCallback { 46 | override fun onSuccess(promotionInfo: PromotionInfo?) { 47 | taskParam.put( 48 | ProductTaskConstants.KEY_PRODUCT, 49 | product.apply { promotion = promotionInfo } 50 | ) 51 | notifyTaskSucceed() 52 | } 53 | 54 | override fun onFailed(error: String?) { 55 | notifyTaskFailed(ITaskResult.ERROR, error) 56 | } 57 | }) 58 | .process() 59 | } 60 | 61 | override fun getName(): String { 62 | return "2.3 获取商品的促销信息" 63 | } 64 | } -------------------------------------------------------------------------------- /app/src/main/java/com/xuexiang/kotlinsample/fragment/coroutines/concurrent/task/GetRichInfoTask.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2022 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.fragment.coroutines.concurrent.task 18 | 19 | import com.xuexiang.kotlinsample.fragment.coroutines.business.processor.AbstractProcessor 20 | import com.xuexiang.kotlinsample.fragment.coroutines.business.task.AbstractTask 21 | import com.xuexiang.kotlinsample.fragment.coroutines.business.task.ProductTaskConstants 22 | import com.xuexiang.kotlinsample.fragment.coroutines.concurrent.entity.Product 23 | import com.xuexiang.kotlinsample.fragment.coroutines.concurrent.entity.RichInfo 24 | import com.xuexiang.kotlinsample.fragment.coroutines.concurrent.processor.GetRichInfoProcessor 25 | import com.xuexiang.xtask.core.param.ITaskResult 26 | import com.xuexiang.xui.widget.textview.LoggerTextView 27 | import com.xuexiang.xutil.common.StringUtils 28 | 29 | /** 30 | * 2.4 获取商品的富文本信息 31 | * 32 | * @author xuexiang 33 | * @since 3/23/22 12:18 AM 34 | */ 35 | class GetRichInfoTask(logger: LoggerTextView?) : AbstractTask(logger) { 36 | @Throws(Exception::class) 37 | override fun doTask() { 38 | val product: Product? = taskParam.getObject(ProductTaskConstants.KEY_PRODUCT, Product::class.java) 39 | if (product == null || StringUtils.isEmpty(product.richId)) { 40 | notifyTaskFailed(ITaskResult.ERROR, "product is null or richId is empty!") 41 | return 42 | } 43 | GetRichInfoProcessor(mLogger, product.richId!!) 44 | .setProcessorCallback(object : AbstractProcessor.IProcessorCallback { 45 | override fun onSuccess(richInfo: RichInfo?) { 46 | taskParam.put(ProductTaskConstants.KEY_PRODUCT, product.apply { rich = richInfo }) 47 | notifyTaskSucceed() 48 | } 49 | 50 | override fun onFailed(error: String?) { 51 | notifyTaskFailed(ITaskResult.ERROR, error) 52 | } 53 | }) 54 | .process() 55 | } 56 | 57 | override fun getName(): String { 58 | return "2.4 获取商品的富文本信息" 59 | } 60 | } -------------------------------------------------------------------------------- /app/src/main/java/com/xuexiang/kotlinsample/utils/XToastUtils.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.utils 18 | 19 | import androidx.annotation.MainThread 20 | import com.xuexiang.xui.widget.toast.XToast 21 | import com.xuexiang.xui.XUI 22 | import androidx.annotation.StringRes 23 | import java.lang.UnsupportedOperationException 24 | 25 | /** 26 | * xtoast 工具类 27 | * 28 | * @author xuexiang 29 | * @since 2019-06-30 19:04 30 | */ 31 | class XToastUtils private constructor() { 32 | 33 | companion object { 34 | //======普通土司=======// 35 | @MainThread 36 | fun toast(message: CharSequence) { 37 | XToast.normal(XUI.getContext(), message).show() 38 | } 39 | 40 | @MainThread 41 | fun toast(@StringRes message: Int) { 42 | XToast.normal(XUI.getContext(), message).show() 43 | } 44 | 45 | @MainThread 46 | fun toast(message: CharSequence, duration: Int) { 47 | XToast.normal(XUI.getContext(), message, duration).show() 48 | } 49 | 50 | @MainThread 51 | fun toast(@StringRes message: Int, duration: Int) { 52 | XToast.normal(XUI.getContext(), message, duration).show() 53 | } 54 | 55 | //======错误【红色】=======// 56 | @MainThread 57 | fun error(message: CharSequence) { 58 | XToast.error(XUI.getContext(), message).show() 59 | } 60 | 61 | @MainThread 62 | fun error(@StringRes message: Int) { 63 | XToast.error(XUI.getContext(), message).show() 64 | } 65 | 66 | @MainThread 67 | fun error(message: CharSequence, duration: Int) { 68 | XToast.error(XUI.getContext(), message, duration).show() 69 | } 70 | 71 | @MainThread 72 | fun error(@StringRes message: Int, duration: Int) { 73 | XToast.error(XUI.getContext(), message, duration).show() 74 | } 75 | 76 | //======成功【绿色】=======// 77 | @MainThread 78 | fun success(message: CharSequence) { 79 | XToast.success(XUI.getContext(), message).show() 80 | } 81 | 82 | @MainThread 83 | fun success(@StringRes message: Int) { 84 | XToast.success(XUI.getContext(), message).show() 85 | } 86 | 87 | @MainThread 88 | fun success(message: CharSequence, duration: Int) { 89 | XToast.success(XUI.getContext(), message, duration).show() 90 | } 91 | 92 | @MainThread 93 | fun success(@StringRes message: Int, duration: Int) { 94 | XToast.success(XUI.getContext(), message, duration).show() 95 | } 96 | 97 | //======信息【蓝色】=======// 98 | @MainThread 99 | fun info(message: CharSequence) { 100 | XToast.info(XUI.getContext(), message).show() 101 | } 102 | 103 | @MainThread 104 | fun info(@StringRes message: Int) { 105 | XToast.info(XUI.getContext(), message).show() 106 | } 107 | 108 | @MainThread 109 | fun info(message: CharSequence, duration: Int) { 110 | XToast.info(XUI.getContext(), message, duration).show() 111 | } 112 | 113 | @MainThread 114 | fun info(@StringRes message: Int, duration: Int) { 115 | XToast.info(XUI.getContext(), message, duration).show() 116 | } 117 | 118 | //=======警告【黄色】======// 119 | @MainThread 120 | fun warning(message: CharSequence) { 121 | XToast.warning(XUI.getContext(), message).show() 122 | } 123 | 124 | @MainThread 125 | fun warning(@StringRes message: Int) { 126 | XToast.warning(XUI.getContext(), message).show() 127 | } 128 | 129 | @MainThread 130 | fun warning(message: CharSequence, duration: Int) { 131 | XToast.warning(XUI.getContext(), message, duration).show() 132 | } 133 | 134 | @MainThread 135 | fun warning(@StringRes message: Int, duration: Int) { 136 | XToast.warning(XUI.getContext(), message, duration).show() 137 | } 138 | 139 | init { 140 | XToast.Config.get() 141 | .setAlpha(200) 142 | .allowQueue(false) 143 | } 144 | } 145 | 146 | init { 147 | throw UnsupportedOperationException("u can't instantiate me...") 148 | } 149 | } -------------------------------------------------------------------------------- /app/src/main/java/com/xuexiang/kotlinsample/utils/sdkinit/UMengInit.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.utils.sdkinit 18 | 19 | import android.app.Application 20 | import android.content.Context 21 | import com.meituan.android.walle.WalleChannelReader 22 | import com.umeng.analytics.MobclickAgent 23 | import com.umeng.commonsdk.UMConfigure 24 | import com.xuexiang.kotlinsample.BuildConfig 25 | import com.xuexiang.kotlinsample.MyApp 26 | 27 | /** 28 | * UMeng 统计 SDK初始化 29 | * 30 | * @author xuexiang 31 | * @since 2019-06-18 15:49 32 | */ 33 | class UMengInit private constructor() { 34 | companion object { 35 | private const val DEFAULT_CHANNEL_ID = "github" 36 | 37 | /** 38 | * 初始化SDK,合规指南【先进行预初始化,如果用户隐私同意后可以初始化UmengSDK进行信息上报】 39 | */ 40 | fun init(context: Context) { 41 | val appContext = context.applicationContext 42 | if (appContext is Application) { 43 | initApplication(appContext) 44 | } 45 | } 46 | 47 | /** 48 | * 初始化SDK,合规指南【先进行预初始化,如果用户隐私同意后可以初始化UmengSDK进行信息上报】 49 | * 50 | * @param application 应用上下文 51 | */ 52 | private fun initApplication(application: Application) { 53 | // 运营统计数据调试运行时不初始化 54 | if (MyApp.isDebug) { 55 | return 56 | } 57 | UMConfigure.setLogEnabled(false) 58 | UMConfigure.preInit(application, BuildConfig.APP_ID_UMENG, getChannel(application)) 59 | // 用户同意了隐私协议 60 | if (isAgreePrivacy) { 61 | realInit(application) 62 | } 63 | }// TODO: 2021/5/11 隐私协议设置 64 | 65 | /** 66 | * @return 用户是否同意了隐私协议 67 | */ 68 | private val isAgreePrivacy: Boolean 69 | private get() =// TODO: 2021/5/11 隐私协议设置 70 | true 71 | 72 | /** 73 | * 真实的初始化UmengSDK【进行设备信息的统计上报,必须在获得用户隐私同意后方可调用】 74 | */ 75 | private fun realInit(application: Application) { 76 | // 运营统计数据调试运行时不初始化 77 | if (MyApp.isDebug) { 78 | return 79 | } 80 | //初始化组件化基础库, 注意: 即使您已经在AndroidManifest.xml中配置过appkey和channel值,也需要在App代码中调用初始化接口(如需要使用AndroidManifest.xml中配置好的appkey和channel值,UMConfigure.init调用中appkey和channel参数请置为null)。 81 | //第二个参数是appkey,最后一个参数是pushSecret 82 | //这里BuildConfig.APP_ID_UMENG是根据local.properties中定义的APP_ID_UMENG生成的,只是运行看效果的话,可以不初始化该SDK 83 | UMConfigure.init(application, BuildConfig.APP_ID_UMENG, getChannel(application), UMConfigure.DEVICE_TYPE_PHONE, "") 84 | //统计SDK是否支持采集在子进程中打点的自定义事件,默认不支持 85 | //支持多进程打点 86 | UMConfigure.setProcessEvent(true) 87 | MobclickAgent.setPageCollectionMode(MobclickAgent.PageMode.AUTO) 88 | } 89 | 90 | /** 91 | * 获取渠道信息 92 | */ 93 | private fun getChannel(context: Context): String? { 94 | return WalleChannelReader.getChannel(context, DEFAULT_CHANNEL_ID) 95 | } 96 | } 97 | 98 | init { 99 | throw UnsupportedOperationException("u can't instantiate me...") 100 | } 101 | } -------------------------------------------------------------------------------- /app/src/main/java/com/xuexiang/kotlinsample/utils/sdkinit/XBasicLibInit.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.utils.sdkinit 18 | 19 | import android.app.Application 20 | import com.xuexiang.kotlinsample.MyApp 21 | import com.xuexiang.kotlinsample.core.BaseActivity 22 | import com.xuexiang.kotlinsample.utils.XToastUtils 23 | import com.xuexiang.xaop.XAOP 24 | import com.xuexiang.xpage.PageConfig 25 | import com.xuexiang.xrouter.launcher.XRouter 26 | import com.xuexiang.xui.XUI 27 | import com.xuexiang.xutil.XUtil 28 | import com.xuexiang.xutil.common.StringUtils 29 | 30 | /** 31 | * X系列基础库初始化 32 | * 33 | * @author xuexiang 34 | * @since 2019-06-30 23:54 35 | */ 36 | class XBasicLibInit private constructor() { 37 | companion object { 38 | /** 39 | * 初始化基础库SDK 40 | */ 41 | fun init(application: Application) { 42 | //工具类 43 | initXUtil(application) 44 | 45 | //页面框架 46 | initXPage(application) 47 | 48 | //切片框架 49 | initXAOP(application) 50 | 51 | //UI框架 52 | initXUI(application) 53 | 54 | //路由框架 55 | initRouter(application) 56 | } 57 | 58 | /** 59 | * 初始化XUtil工具类 60 | */ 61 | private fun initXUtil(application: Application) { 62 | XUtil.init(application) 63 | XUtil.debug(MyApp.isDebug) 64 | } 65 | 66 | /** 67 | * 初始化XPage页面框架 68 | */ 69 | private fun initXPage(application: Application) { 70 | PageConfig.getInstance() 71 | .debug(MyApp.isDebug) 72 | .setContainActivityClazz(BaseActivity::class.java) 73 | .init(application) 74 | } 75 | 76 | /** 77 | * 初始化XAOP 78 | */ 79 | private fun initXAOP(application: Application) { 80 | XAOP.init(application) 81 | XAOP.debug(MyApp.isDebug) 82 | //设置动态申请权限切片 申请权限被拒绝的事件响应监听 83 | XAOP.setOnPermissionDeniedListener { permissionsDenied: List? -> XToastUtils.error("权限申请被拒绝:" + StringUtils.listToString(permissionsDenied, ",")) } 84 | } 85 | 86 | /** 87 | * 初始化XUI框架 88 | */ 89 | private fun initXUI(application: Application) { 90 | XUI.init(application) 91 | XUI.debug(MyApp.isDebug) 92 | } 93 | 94 | /** 95 | * 初始化路由框架 96 | */ 97 | private fun initRouter(application: Application) { 98 | // 这两行必须写在init之前,否则这些配置在init过程中将无效 99 | if (MyApp.isDebug) { 100 | XRouter.openLog() // 打印日志 101 | XRouter.openDebug() // 开启调试模式(如果在InstantRun模式下运行,必须开启调试模式!线上版本需要关闭,否则有安全风险) 102 | } 103 | XRouter.init(application) 104 | } 105 | } 106 | 107 | init { 108 | throw UnsupportedOperationException("u can't instantiate me...") 109 | } 110 | } -------------------------------------------------------------------------------- /app/src/main/java/com/xuexiang/kotlinsample/utils/service/JsonSerializationService.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.utils.service 18 | 19 | import android.content.Context 20 | import com.xuexiang.xrouter.annotation.Router 21 | import com.xuexiang.xrouter.facade.service.SerializationService 22 | import com.xuexiang.xutil.net.JsonUtil 23 | import java.lang.reflect.Type 24 | 25 | /** 26 | * @author XUE 27 | * @since 2019/3/27 16:39 28 | */ 29 | @Router(path = "/service/json") 30 | class JsonSerializationService : SerializationService { 31 | /** 32 | * 对象序列化为json 33 | * 34 | * @param instance obj 35 | * @return json string 36 | */ 37 | override fun object2Json(instance: Any): String { 38 | return JsonUtil.toJson(instance) 39 | } 40 | 41 | /** 42 | * json反序列化为对象 43 | * 44 | * @param input json string 45 | * @param clazz object type 46 | * @return instance of object 47 | */ 48 | override fun parseObject(input: String, clazz: Type): T { 49 | return JsonUtil.fromJson(input, clazz) 50 | } 51 | 52 | /** 53 | * 进程初始化的方法 54 | * 55 | * @param context 上下文 56 | */ 57 | override fun init(context: Context) {} 58 | } -------------------------------------------------------------------------------- /app/src/main/res/drawable-v24/ic_launcher_foreground.xml: -------------------------------------------------------------------------------- 1 | 7 | 12 | 13 | 19 | 22 | 25 | 26 | 27 | 28 | 34 | 35 | -------------------------------------------------------------------------------- /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/adapter_item_simple_list_2.xml: -------------------------------------------------------------------------------- 1 | 17 | 26 | 27 | 31 | 32 | 37 | 38 | -------------------------------------------------------------------------------- /app/src/main/res/layout/fragment_usecase_compare.xml: -------------------------------------------------------------------------------- 1 | 17 | 18 | 22 | 23 | 29 | 30 |