添加依赖
- Retrofit,声明式网络请求客户端
- coroutines-core,协程核心库
- coroutines-android,协程安卓适配库
- lifecycle-viewmodel-ktx,ViewModel拓展函数支持库
- lifecycle-livedata-core-ktx、lifecycle-livedata-ktx,将Flow转换为LiveData的库
// Retrofit
implementation('com.squareup.retrofit2:retrofit:2.9.0')
// 协程
implementation('org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.0')
implementation('org.jetbrains.kotlinx:kotlinx-coroutines-android:1.7.1')
// 使用拓展库
implementation("androidx.lifecycle:lifecycle-extensions:2.2.0")
// ViewModel拓展函数
implementation("androidx.lifecycle:lifecycle-viewmodel-ktx:2.8.7")
// 提供lifecycleScope支持
implementation("androidx.lifecycle:lifecycle-runtime-ktx:2.8.7")
// LiveData拓展函数
implementation("androidx.lifecycle:lifecycle-livedata-core-ktx:2.8.7")
implementation("androidx.lifecycle:lifecycle-livedata-ktx:2.8.7")
基础封装
Retrofit管理类
object RetrofitManager {
private fun getOKHttpClient(timeout: Long): OkHttpClient {
// 日志打印拦截器
val logInterceptor = HttpLoggingInterceptor {
LogTool.d("HttpLoggingInterceptor $it")
}.setLevel(HttpLoggingInterceptor.Level.BODY)
val interceptors: MutableList<Interceptor> = ArrayList()
// 添加自定义拦截器
val builder = OkHttpClient().newBuilder()
.callTimeout(timeout, TimeUnit.SECONDS)
.connectTimeout(timeout, TimeUnit.SECONDS)
.readTimeout(timeout, TimeUnit.SECONDS)
.writeTimeout(timeout, TimeUnit.SECONDS)
.retryOnConnectionFailure(true)
.followRedirects(false)
.addInterceptor(logInterceptor)
// 添加拦截器
builder.interceptors().addAll(interceptors)
return builder.build()
}
private fun getRetrofit(timeout: Long): Retrofit {
return Retrofit.Builder()
.client(getOKHttpClient(timeout))
.baseUrl("apiUrl")
.addConverterFactory(GsonConvertFactory.create())
.build()
}
fun <T> getService(service: Class<T>, timeout: Long = 10): T {
return getRetrofit(timeout).create(service)
}
}
ViewModel基类
typealias block = suspend () -> Unit
open class BaseViewModel : ViewModel(), DefaultLifecycleObserver {
protected fun launch(
block: block
): Job {
return viewModelScope.launch {
try {
block.invoke()
} catch (e: Exception) {
e.printStackTrace()
}
}
}
}
仓库层基类
open class BaseRepository {
/**
* 处理状态
*/
fun <T> BaseResp<T>.handleState(): BaseResp<T> {
try {
when (this.code) {
Constants.HTTP_SUCCESS -> {
// 请求成功
}
Constants.HTTP_AUTH_INVALID -> {
// token过期,清除token,跳转去登录页
}
}
} catch (e: Exception) {
when (e) {
is UnknownHostException,
is HttpException,
is ConnectException,
-> {
// 网络错误
}
else -> {
}
}
}
return this
}
}
编写网络层
响应结果的实体类
class BaseResp<T> {
var code: Int = -1
var msg: String = ""
var data: List<T>? = null
companion object {
/**
* 错误响应
*/
fun <T> errorResp(): BaseResp<T> {
return BaseResp<T>().apply {
code = -1
msg = "请求失败,请稍后重试"
data = null
}
}
}
}
Api接口
interface Api {
/**
* 获取当前用户信息
*/
@POST("getUserInfo")
suspend fun getUserInfo(@Body req: BodyReq<EmptyT>): BaseResp<CurrentUserInfo>
/**
* 保存用户信息
*/
@POST("saveUserInfo")
suspend fun saveUserInfo(@Body req: BodyReq<UserInfo>): BaseResp<*>
/**
* 获取App配置
*/
@POST("getAppConfig")
suspend fun getAppConfig(@Body req: BodyReq<AppInfo>): BaseResp<AppConfig>
/**
* 获取数据列表
*/
@GET("getDataList")
fun getDataList(): Call<BaseResp<DataList>>
}
Repository仓库层
/**
* 用户信息相关Repository
*/
open class UserRepository(private val api: Api) : BaseRepository() {
/**
* 获取当前用户信息
*/
fun getUserInfo(): Flow<BaseResp<CurrentUserInfo>> = flow {
val result = api.getUserInfo(
BodyReq()
).handleState()
emit(result)
}.flowOn(Dispatchers.IO).catch {
emit(BaseResp.errorResp())
}
/**
* 保存用户基本信息
*/
fun saveUserInfo(
req: UserInfo
): Flow<BaseResp<*>> = flow {
val result = api.saveUserInfo(
BodyReq()
).handleState()
emit(result)
}.flowOn(Dispatchers.IO).catch {
emit(BaseResp.errorResp())
}
/**
* 获取App配置
*/
fun getAppConfig(
req: AppInfo
): Flow<BaseResp<AppPageConfig>>{
return flow {
val resp = api.getAppConfig(req).handleState()
emit(resp)
}.flowOn(Dispatchers.IO).catch {
emit(BaseResp.errorResp())
}
}
}
ViewModel层
/**
* 用户信息ViewModel
*/
open class UserInfoViewModel(private val repo: UserInfoRepository) : BaseViewModel() {
val appConfigLiveData = MutableLiveData<AppPageConfig>>()
/**
* 获取当前用户信息
*/
fun getUserInfo() = liveData {
emit(repo.getUserInfo().single())
}
/**
* 保存用户基本信息
*/
fun saveUserInfo(req: UserInfo) = liveData {
emit(repo.saveUserInfo(req).single())
}
/**
* 获取App配置
*/
fun getAppConfig(req: AppInfo) = launch {
repo.getAppConfig(req).collect{value->
appConfigLiveData.value = value.data
}
}
}
ViewModel管理类
object ViewModelManager {
private val mApi by lazy {
RetrofitManager.getService(Api::class.java, 45)
}
class UserInfoViewModelFactory(
private val repo: UserInfoRepository
) : ViewModelProvider.Factory {
override fun <T : ViewModel> create(modelClass: Class<T>): T {
if (modelClass.isAssignableFrom(UserInfoViewModel::class.java)) {
return UserInfoViewModel(repo) as T
} else {
throw IllegalArgumentException("Unknown ViewModel Class")
}
}
}
/**
* 获取用户信息的ViewModel
*/
fun getUserInfoViewModel(
owner: ViewModelStoreOwner
): UserInfoViewModel {
val repo = UserInfoRepository(mApi)
ViewModelProvider(
owner,
UserInfoViewModelFactory(repo)
)[UserInfoViewModel::class.java]
}
}
基础使用
ViewModelManager.getUserInfoViewModel()
.saveUserInfo(req)
.observe(
lifecycleOwner,
object : BaseObserver<UserInfo>() {
override fun getRespDataSuccess(it: PResDataEmptyT) {
super.getRespDataSuccess(it)
// 获取用户信息成功
}
override fun getRespDataEnd(code: Int, errorMsg: String) {
super.getRespDataEnd(code, errorMsg)
// 获取用户信息失败
}
})
直接在Activity、Fragment中使用
private val mainScope: CoroutineScope = MainScope()
mainScope.launch {
withContext(Dispatchers.IO) {
val appConfig = repo.getAppConfig(req)
appConfigLiveData.postValue(appConfig)
}
}
lifecycleScope.launch {
try {
// 发起请求
getDataList()
} catch (e: Exception) {
// 处理异常情况
e.printStackTrace()
hideLoading()
}
}
private suspend fun getDataList() {
try {
val response = withContext(Dispatchers.IO) {
request.getDataList().execute()
}
if (response.isSuccessful) {
val body = response.body()
// 请求成功
}
} catch (e: Exception) {
// 处理异常
e.printStackTrace()
} finally {
hideLoading()
}
}