网络请求
相关依赖
- Retrofit:https://square.github.io/retrofit/
- OkHttp:https://square.github.io/okhttp/
- HttpLoggingInterceptor:https://github.com/square/okhttp/tree/master/okhttp-logging-interceptor
- Chucker:https://github.com/ChuckerTeam/chucker
- 版本配置:
gradle/libs.versions.toml中的retrofit、okhttp、logging-interceptor、chucker
app/src/main/java/com/joker/kit/core/network 负责 Retrofit + OkHttp 的统一封装,并通过 DataSource/Service 的分层为 core/data 仓库提供网络数据。模块包含以下子目录:
base/:抽象基类,提供Retrofit.createService()等工具。service/:Retrofit 接口,定义 HTTP 方法与路径。datasource/:网络数据源,组合 Service 并对外提供挂起函数。interceptor/:认证、日志、调试拦截器。di/:Hilt 模块,注入 Retrofit、OkHttp、Service、DataSource。
依赖与 BuildConfig
app/build.gradle.kts 中已经集成 Retrofit、OkHttp、Chucker 等依赖,同时通过 buildConfigField 定义 BASE_URL 与 DEBUG(依赖版本集中在 gradle/libs.versions.toml,每个库都附上官方文档链接,方便查阅/升级):
buildTypes {
debug {
buildConfigField("String", "BASE_URL", "\"https://box.dusksnow.top/app/\"")
buildConfigField("Boolean", "DEBUG", "true")
}
release {
buildConfigField("String", "BASE_URL", "\"https://box.dusksnow.top/app/\"")
buildConfigField("Boolean", "DEBUG", "false")
}
}修改请求地址:直接在对应的 buildType 中调整 BASE_URL(或使用不同的 Gradle property)。所有 Retrofit 实例会读取 BuildConfig.BASE_URL。
NetworkModule(Retrofit/OkHttp)
NetworkModule 提供 Retrofit 与 OkHttp 实例:
- OkHttp 拦截器链:
AuthInterceptor(读取本地 token 并写入 Header)、HttpLoggingInterceptor(根据 BuildConfig.DEBUG 控制日志级别)、调试环境下注入ChuckerInterceptor方便抓包。 - 超时重试:连接/读写超时均为 10 秒,开启
retryOnConnectionFailure(true)。 - 序列化:使用
kotlinx.serialization转换器,配置了ignoreUnknownKeys等参数,避免服务端字段变更导致解析失败。
拦截器
AuthInterceptor:调用AuthStoreDataSource.getToken()(runBlocking)获取 token,若存在则添加到AuthorizationHeader。LoggingInterceptor:封装HttpLoggingInterceptor,打印请求/响应日志;release 版本关闭日志。- Chucker:在
NetworkModule的 OkHttp 构建中if (BuildConfig.DEBUG)加入ChuckerInterceptor,可在手机上查看 HTTP 抓包。
真正的调用链:Service → DataSource → Repository
以下以 商品模块 为例说明整个调用链。
1. Service(core/network/service/GoodsService.kt)
interface GoodsService {
@POST("goods/info/page")
suspend fun getGoodsPage(@Body params: GoodsSearchRequest): NetworkResponse<NetworkPageData<Goods>>
@GET("goods/info/info")
suspend fun getGoodsInfo(@Query("id") id: String): NetworkResponse<Goods>
}2. DataSource(core/network/datasource/goods/)
- 接口
GoodsNetworkDataSource.kt:
interface GoodsNetworkDataSource {
suspend fun getGoodsPage(params: GoodsSearchRequest): NetworkResponse<NetworkPageData<Goods>>
suspend fun getGoodsInfo(id: String): NetworkResponse<Goods>
}- 实现
GoodsNetworkDataSourceImpl.kt:
class GoodsNetworkDataSourceImpl @Inject constructor(
private val goodsService: GoodsService
) : BaseNetworkDataSource(), GoodsNetworkDataSource {
override suspend fun getGoodsPage(params: GoodsSearchRequest) =
goodsService.getGoodsPage(params)
override suspend fun getGoodsInfo(id: String) =
goodsService.getGoodsInfo(id)
}3. Repository(core/data/repository/GoodsRepository.kt)
class GoodsRepository @Inject constructor(
private val goodsNetworkDataSource: GoodsNetworkDataSource
) {
fun getGoodsPage(params: GoodsSearchRequest): Flow<NetworkResponse<NetworkPageData<Goods>>> =
flow { emit(goodsNetworkDataSource.getGoodsPage(params)) }
.flowOn(Dispatchers.IO)
fun getGoodsInfo(id: String): Flow<NetworkResponse<Goods>> =
flow { emit(goodsNetworkDataSource.getGoodsInfo(id)) }
.flowOn(Dispatchers.IO)
}通过这条链路,Feature ViewModel 只需注入 GoodsRepository 即可发起网络请求,而无须了解 Retrofit/OkHttp 的细节。
4. 依赖注入(core/network/di/ServiceModule.kt & core/network/di/DataSourceModule.kt)
// ServiceModule.kt
@Provides
@Singleton
fun provideGoodsService(retrofit: Retrofit): GoodsService =
retrofit.create(GoodsService::class.java)// DataSourceModule.kt
@Provides
@Singleton
fun provideGoodsNetworkDataSource(goodsService: GoodsService): GoodsNetworkDataSource =
GoodsNetworkDataSourceImpl(goodsService)记得在新增 Service/DataSource 时同步更新两个 Module,否则 Hilt 无法注入。
依赖注入
ServiceModule:使用 Retrofit 创建所有 Service。DataSourceModule:创建对应的 NetworkDataSource。NetworkModule:提供 Retrofit、OkHttp、Json、LoggingInterceptor。
所有模块都 @InstallIn(SingletonComponent::class),因此可在任意 Hilt 作用域中注入。
添加新接口流程(以 Cart 为例)
- 定义实体/请求体(
core/model)kotlin@Serializable data class AddCartRequest(val goodsId: Long, val count: Int) - Service(
core/network/service/CartService.kt)kotlininterface CartService { @POST("cart/add") suspend fun addToCart(@Body request: AddCartRequest): NetworkResponse<Unit> } - DataSource(
core/network/datasource/cart)kotlin// CartNetworkDataSource.kt interface CartNetworkDataSource { suspend fun addToCart(request: AddCartRequest): NetworkResponse<Unit> }kotlin// CartNetworkDataSourceImpl.kt class CartNetworkDataSourceImpl @Inject constructor( private val cartService: CartService ) : BaseNetworkDataSource(), CartNetworkDataSource { override suspend fun addToCart(request: AddCartRequest) = cartService.addToCart(request) } - DI 注册kotlin
// ServiceModule.kt @Provides @Singleton fun provideCartService(retrofit: Retrofit): CartService = retrofit.create(CartService::class.java)kotlin// DataSourceModule.kt @Provides @Singleton fun provideCartNetworkDataSource(cartService: CartService): CartNetworkDataSource = CartNetworkDataSourceImpl(cartService) - Repository(
core/data/repository/CartRepository.kt)kotlinclass CartRepository @Inject constructor( private val cartNetworkDataSource: CartNetworkDataSource ) { fun addToCart(request: AddCartRequest): Flow<NetworkResponse<Unit>> = flow { emit(cartNetworkDataSource.addToCart(request)) } .flowOn(Dispatchers.IO) } - ViewModel/UseCase
注入CartRepository,直接调用对应方法并结合BaseNetWorkViewModel处理三态 UI。
调试与日志
- HttpLoggingInterceptor:默认 debug 打印 BODY,release 关闭;可根据需求调整级别。
- Chucker:在 debug 包内会自动弹出通知,可查看每一次请求的 Header/Body。如果需要禁用,直接移除
debugImplementation(libs.chucker)或在NetworkModule中移除addInterceptor(ChuckerInterceptor...)。
关联 DataStore & Auth
AuthInterceptor 使用 AuthStoreDataSource 读取 token,因此必须先在 DataStore 层保存认证信息(如登录成功后调用 AuthStoreRepository.saveAuth())。一旦 token 变更,新的请求会自动携带最新的 Header。
常见定制点
- 切换 BaseUrl:修改
buildConfigField("BASE_URL", "...")或使用多环境构建(flavor/BuildConfig)。 - 超时设置:在
NetworkModule.provideOkHttpClient中调整connectTimeout/readTimeout等参数。 - 证书/代理:在 OkHttp Builder 中追加
sslSocketFactory、proxy等配置。 - 错误处理:网络层只负责发请求,错误处理在
core/result模块中进行(ResultHandler)。如需统一拦截 401,可在拦截器中判断状态码并触发登出。
通过这种模块化结构,网络请求的新增/修改都集中在 core/network + core/data,上层 Feature 只需调用 Repository 即可,极大地提高了可维护性和可测试性。
- 相关依赖版本可在
gradle/libs.versions.toml中查看(okhttp、logging-interceptor、chucker条目都附带官方链接)。