Android协程和Flow使用记录

添加依赖

  • 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()
    }
}
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容