文章目录
1:前言
玩Android APP 源码
学习kotlin,学习Android,最好的方式就是看别人的APP源码, 手头有一份玩安卓APP的kotlin版本,适合学习使用,文中提到的代码都在这款APP的源码里
WanAndroid基础款(MVVM+Kotlin+Jetpack+组件化)
本贴的目的
主要目的是基于WanAndroid基础款(MVVM+Kotlin+Jetpack+组件化)这份源码, 学习kotlin开发, 顺便记录学习过程中一些相关知识.
1.了解在模块化下,使用Retrofit + 协程 + viewModel, 怎么用完成网络层 , 数据的处理
2. 复盘学习过程,记录思路的变化,加深对语言的理解
3.记录以供后期翻阅(或触类旁通,毕竟好记性不如烂笔头)
参考贴
2: kotlin下的模块化(捎带一嘴)
基本和Java语言下的模块化配置差不多,主要是配置gradle,可以看这个
[Android 模块化配置实践] Java + Gradle7配置模块化实践记录
本项目的模块化截图:
从项目结构上看, lib_common模块里面,回提供基础的网络层封装, 在lib_home等业务模块中,依赖 lib_common提供的各项功能
//在lib_home中依赖 lib_common
dependencies {
// 引入模块 lib_common
implementation project(path: ':lib_common')
}
3:Retrofit+协程+viewModel
乍一看APP源码, 确实有点晕的,所以我们拆分一下,先看我们熟悉的Retrofit部分
其实看完了Retrofit部分,我才发现,Retrofit是结合了协程一起的,所以第一步先尝试使用Retrofit+协程 ,完成简单的网络调用,再去结合viewModel会更加容易,也更符合开发顺序
至于为什么要结合协程?
// 不使用协程,返回值是Call类型,或者比如Java结合RxJava返回FLow
interface IApiServices {
@GET("getHealthCare")
fun getAllHealthData(@Query("userId") userId: String):Call<AllHealthBean>
}
// 使用协程,返回值直接就是你定义的数据类型或者Bean,直接就是可以使用
interface IApiServices {
@GET("getHealthCare")
suspend fun getAllHealthData(@Query("userId") userId: String):AllHealthBean
}
总之,Retrofit结合协程, 获取请求结果,使用起来更加方便, 这就有点类似 JS的 async/await
3.1基础网络层搭建
(http请求及数据展示)
先看看APP的接口
https://www.wanandroid.com/banner/json
{
"data":[{
"desc":"我们支持订阅啦~","id":30,"imagePath":"https://www.wanandroid.com/blogimgs/42da12d8-de56-4439-b40c-eab66c227a4b.png","isVisible":1,"order":2,"title":"我们支持订阅啦~","type":0,"url":"https://www.wanandroid.com/blog/show/3352"},{
"desc":"","id":6,"imagePath":"https://www.wanandroid.com/blogimgs/62c1bd68-b5f3-4a3c-a649-7ca8c7dfabe6.png","isVisible":1,"order":1,"title":"我们新增了一个常用导航Tab~","type":1,"url":"https://www.wanandroid.com/navi"},{
"desc":"一起来做个App吧","id":10,"imagePath":"https://www.wanandroid.com/blogimgs/50c115c2-cf6c-4802-aa7b-a4334de444cd.png","isVisible":1,"order":1,"title":"一起来做个App吧","type":1,"url":"https://www.wanandroid.com/blog/show/2"}],"errorCode":0,"errorMsg":""}
lib_home:Banner
(以上获取banner数据的bean类)
package com.example.lib_home.bean
/**
* @author: tiannan
* @time: 2023/6/2.
* @email: tianNanYiHao@163.com
* @descripetion: 此处添加描述
*/
data class Banner(
val desc: String,
val id: Int,
val imagePath: String,
val isVisible: Int,
val order: Int,
val title: String,
val type: Int,
val url: String
)
lib_common: BaseResp
( common模块下的Http请求的基本返回类)
http请求 也就是
code
,msg
,data
, 前两个没什么好说的, 都是基本型数据, 唯独data
可能是数组,可能是集合,类型不固定
只能在具体的请求数据里,定义出了相对应的Bean,才能说给出一个类型,所以这里的data,理所当然的用到泛型
APP源码中用了 T 作为data属性的泛型类型
class BaseResp<D> {
var errorCode: Int = -1
var errorMsg: String = ""
var data: D? = null
var responseState: ResponseState? = null //请求状态
enum class ResponseState {
REQUEST_START,
REQUEST_SUCCESS,
REQUEST_FAILED,
REQUEST_ERROR
}
}
// PS : 我自己的练习Demo中, 我把T改成了D,好方便我自己理解, D = data
lib_common:RetrofitManager
common模块下的Retrofit管理类(单例模式)
这个没太多可以说的, Retrofit的使用不是很复杂
package com.example.lib_common.net
import android.util.Log
import okhttp3.OkHttpClient
import okhttp3.logging.HttpLoggingInterceptor
import retrofit2.Retrofit
import retrofit2