黄金网络框架组合:Okhttp+Retrofit+协程+Gson

5 阅读10分钟

本项目实现了一套完整的Android网络请求框架,基于OkHttp + Retrofit + 协程 + Gson的黄金组合,提供了统一的响应格式、完善的异常处理、自动日志记录、Token管理和智能缓存等功能。

博主在之前的毕设项目搭建过程中使用过这个Okhttp+Retrofit这一套,可以说非常优雅,扩展性也比较好。因为工作中接触应用层比较少了,今天一时兴起想起写一篇文章,万一哪天被裁了,也好向上兼容找一个应用开发的岗位,哈哈哈...

1.项目依赖版本

- **OkHttp 4.12.0** - 底层HTTP客户端
- **Retrofit 2.9.0** - RESTful API封装
- **Gson 2.10.1** - JSON序列化/反序列化
- **Kotlin Coroutines 1.7.3** - 异步编程支持
- **Lifecycle Runtime KTX 2.7.0** - 生命周期感知的协程支持
dependencies {
    // OkHttp
    implementation("com.squareup.okhttp3:okhttp:4.12.0")

    // Retrofit
    implementation("com.squareup.retrofit2:retrofit:2.9.0")
    implementation("com.squareup.retrofit2:converter-gson:2.9.0")

    // Gson
    implementation("com.google.code.gson:gson:2.10.1")

    // Coroutines
    implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.7.3")

    // Lifecycle
    implementation("androidx.lifecycle:lifecycle-runtime-ktx:2.7.0")

2.项目结构

com.zzzjian.networkdemo
├── MainActivity.kt                          # 主Activity,使用示例
└── network
    ├── BaseResponse.kt                      # 统一响应格式
    ├── Result.kt                            # 请求结果封装
    ├── RetrofitClient.kt                    # Retrofit客户端单例
    ├── ApiService.kt                        # API接口定义
    ├── RequestExtensions.kt                 # 请求扩展函数和异常处理
    └── interceptor
        ├── LogInterceptor.kt                # 日志拦截器
        ├── TokenInterceptor.kt              # Token拦截器
        └── CacheInterceptor.kt              # 缓存拦截器

3.组件作用

1. BaseResponse.kt - 统一响应格式

  • 作用:定义服务器返回数据的统一格式,所有API接口的响应都遵循这个结构。
  • 在网络链路中的位置:作为Retrofit接口方法的返回类型,接收服务器返回的原始数据。
data class BaseResponse<T>(
    @SerializedName("code")
    val code: Int = 0,
    @SerializedName("message")
    val message: String = "",
    @SerializedName("data")
    val data: T? = null
) {
    val isSuccess: Boolean
        get() = code == 0
}

2.Result.kt - 请求结果封装

  • 作用:使用密封类封装网络请求的三种状态(成功、失败、加载中),提供类型安全的处理方式。
  • 在网络链路中的位置:作为safeApiCall函数的返回值,将BaseResponse转换为更易处理的Result对象。

sealed class Result<out T> {
    data class Success<T>(val data: T) : Result<T>()
    data class Error(val exception: Exception) : Result<Nothing>()
    object Loading : Result<Nothing>()
}

/**
 * 成功状态处理扩展函数
 * 作用:当Result为Success状态时执行指定操作
 */
inline fun <T> Result<T>.onSuccess(action: (T) -> Unit): Result<T> {
    if (this is Result.Success) action(data)
    return this
}

/**
 * 失败状态处理扩展函数
 * 作用:当Result为Error状态时执行指定操作
 */
inline fun <T> Result<T>.onError(action: (Exception) -> Unit): Result<T> {
    if (this is Result.Error) action(exception)
    return this
}

/**
 * 加载中状态处理扩展函数
 * 作用:当Result为Loading状态时执行指定操作
 */
inline fun <T> Result<T>.onLoading(action: () -> Unit): Result<T> {
    if (this is Result.Loading) action()
    return this
}

3. LogInterceptor.kt - 日志拦截器

  • 作用:拦截并打印所有网络请求和响应的详细信息,便于调试和问题排查。
  • 在网络链路中的位置:作为OkHttp的拦截器,在请求发送前和响应接收后执行。
class LogInterceptor : Interceptor {
    override fun intercept(chain: Interceptor.Chain): Response {
        val request = chain.request()

        // 打印请求信息
        println("OkHttp Request: ${request.method} ${request.url}")
        request.headers.forEach { (name, value) ->
            println("OkHttp Request Header: $name = $value")
        }

        val requestBody = request.body
        if (requestBody != null) {
            val buffer = okio.Buffer()
            requestBody.writeTo(buffer)
            val charset = Charset.forName("UTF-8")
            val requestString = buffer.readString(charset)
            println("OkHttp Request Body: $requestString")
        }

        // 执行请求
        val response = chain.proceed(request)

        // 打印响应信息
        println("OkHttp Response: ${response.code} ${response.message}")
        response.headers.forEach { (name, value) ->
            println("OkHttp Response Header: $name = $value")
        }

        val responseBody = response.body
        if (responseBody != null) {
            val source = responseBody.source()
            source.request(Long.MAX_VALUE)
            val buffer = source.buffer
            val charset = Charset.forName("UTF-8")
            val responseString = buffer.clone().readString(charset)
            println("OkHttp Response Body: $responseString")
        }

        return response
    }
}

4. TokenInterceptor.kt - Token拦截器

  • 作用:自动为所有网络请求添加认证Token,避免在每个接口手动添加。
  • 在网络链路中的位置:作为OkHttp的拦截器,在请求发送前自动注入Token到请求头。
// - 统一管理Token,避免重复代码
// - 支持动态设置和清除Token
// - 使用Bearer Token标准认证方式

class TokenInterceptor : Interceptor {
    private var token: String? = null

    /**
     * 设置认证Token
     * @param token 用户登录后获取的Token
     */
    fun setToken(token: String) {
        this.token = token
    }

    /**
     * 清除认证Token
     * 用于用户登出或Token失效时
     */
    fun clearToken() {
        this.token = null
    }

    override fun intercept(chain: Interceptor.Chain): Response {
        val originalRequest = chain.request()
        val requestBuilder = originalRequest.newBuilder()

        token?.let {
            requestBuilder.addHeader("Authorization", "Bearer $it")
        }

        val request = requestBuilder.build()
        return chain.proceed(request)
    }
}

5. CacheInterceptor.kt - 缓存拦截器

  • 作用:为网络响应添加缓存策略,支持离线访问和减少网络请求。
  • 在网络链路中的位置:作为OkHttp的网络拦截器,在响应接收后添加缓存控制头。
class CacheInterceptor : Interceptor {
    override fun intercept(chain: Interceptor.Chain): Response {
        val request = chain.request()
        val response = chain.proceed(request)

        val cacheControl = request.cacheControl.toString()
        if (cacheControl.isEmpty()) {
            response.newBuilder()
                .header("Cache-Control", "public, max-age=60")
                .build()
        }

        return response.newBuilder()
            .removeHeader("Pragma")
            .removeHeader("Cache-Control")
            .header("Cache-Control", "public, max-age=${TimeUnit.MINUTES.toSeconds(10)}")
            .build()
    }
}

6. RetrofitClient.kt - Retrofit客户端单例

  • 作用:统一管理Retrofit和OkHttp的配置,提供API接口的创建方法。
  • 在网络链路中的位置:作为网络请求的入口,负责创建和配置所有网络请求组件。

// - 连接超时:30秒
// - 读取超时:30秒
// - 写入超时:30秒
// - 缓存大小:10MB
// - 自动重试:开启

object RetrofitClient {
    private const val BASE_URL = "https://api.example.com/"
    private const val CACHE_SIZE = 10 * 1024 * 1024L // 10MB

    private val tokenInterceptor = TokenInterceptor()
    private val logInterceptor = LogInterceptor()
    private val cacheInterceptor = CacheInterceptor()

    /**
     * OkHttp客户端配置
     * 包含超时设置、拦截器链、缓存配置等
     */
    private val okHttpClient: OkHttpClient by lazy {
        val cacheDir = File(System.getProperty("java.io.tmpdir"), "okhttp_cache")
        val cache = Cache(cacheDir, CACHE_SIZE)

        OkHttpClient.Builder()
            .connectTimeout(30, TimeUnit.SECONDS)
            .readTimeout(30, TimeUnit.SECONDS)
            .writeTimeout(30, TimeUnit.SECONDS)
            .addInterceptor(tokenInterceptor)
            .addInterceptor(logInterceptor)
            .addNetworkInterceptor(cacheInterceptor)
            .cache(cache)
            .retryOnConnectionFailure(true)
            .build()
    }

    /**
     * Retrofit实例配置
     * 包含BaseUrl、OkHttp客户端、Gson转换器等
     */
    private val retrofit: Retrofit by lazy {
        Retrofit.Builder()
            .baseUrl(BASE_URL)
            .client(okHttpClient)
            .addConverterFactory(GsonConverterFactory.create())
            .build()
    }

    /**
     * 创建API接口实例
     * @param clazz API接口的Class对象
     * @return API接口的实现实例
     */
    fun <T> createApiService(clazz: Class<T>): T {
        return retrofit.create(clazz)
    }

    /**
     * 设置认证Token
     * @param token 用户登录后获取的Token
     */
    fun setToken(token: String) {
        tokenInterceptor.setToken(token)
    }

    /**
     * 清除认证Token
     * 用于用户登出或Token失效时
     */
    fun clearToken() {
        tokenInterceptor.clearToken()
    }
}

7. ApiService.kt - API接口定义

作用:定义所有网络请求的接口方法,使用注解声明请求方式和参数。

在网络链路中的位置:作为业务层与网络层的桥梁,定义具体的API端点。

interface ApiService {
    /**
     * 获取用户信息
     * @return BaseResponse<UserInfo> 用户信息响应
     */
    @GET("user/info")
    suspend fun getUserInfo(): BaseResponse<UserInfo>

    /**
     * 获取用户列表
     * @param page 页码,默认为1
     * @param size 每页数量,默认为20
     * @return BaseResponse<List<UserInfo>> 用户列表响应
     */
    @GET("user/list")
    suspend fun getUserList(
        @Query("page") page: Int = 1,
        @Query("size") size: Int = 20
    ): BaseResponse<List<UserInfo>>

    /**
     * 用户登录
     * @param username 用户名
     * @param password 密码
     * @return BaseResponse<LoginResponse> 登录响应,包含Token和用户信息
     */
    @POST("user/login")
    suspend fun login(
        @Query("username") username: String,
        @Query("password") password: String
    ): BaseResponse<LoginResponse>
}

/**
 * 用户信息数据模型
 */
data class UserInfo(
    val id: Long,
    val username: String,
    val email: String,
    val avatar: String?
)

/**
 * 登录响应数据模型
 */
data class LoginResponse(
    val token: String,
    val userInfo: UserInfo
)

8. RequestExtensions.kt - 请求扩展函数和异常处理

  • 作用: 提供安全的网络请求封装,统一处理异常和响应转换。
  • 在网络链路中的位置:作为业务层调用网络请求的入口,处理所有异常情况。

// - 自动切换到IO线程
// - 统一异常处理
// - 友好的错误提示
// - 将BaseResponse转换为Result

/**
 * 安全的API调用函数
 * 作用:封装网络请求,自动处理异常和响应转换
 * @param apiCall 网络请求的suspend函数
 * @return Result<T> 请求结果,包含成功、失败或加载中状态
 */
suspend fun <T> safeApiCall(
    apiCall: suspend () -> BaseResponse<T>
): Result<T> {
    return withContext(Dispatchers.IO) {
        try {
            val response = apiCall()
            if (response.isSuccess) {
                Result.Success(response.data!!)
            } else {
                Result.Error(ApiException(response.code, response.message))
            }
        } catch (e: Exception) {
            Result.Error(handleException(e))
        }
    }
}

/**
 * 异常处理函数
 * 作用:将原始异常转换为更友好的业务异常
 * @param e 原始异常
 * @return Exception 处理后的异常
 */
fun handleException(e: Exception): Exception {
    return when (e) {
        is UnknownHostException -> NetworkException("网络连接失败,请检查网络设置")
        is SocketTimeoutException -> NetworkException("请求超时,请稍后重试")
        is IOException -> NetworkException("网络错误:${e.message}")
        is ApiException -> e
        else -> UnknownException("未知错误:${e.message}")
    }
}

/**
 * API业务异常
 * 服务器返回的业务错误(如code非0)
 */
class ApiException(val code: Int, override val message: String) : Exception(message)

/**
 * 网络异常
 * 网络连接、超时等网络相关错误
 */
class NetworkException(override val message: String) : Exception(message)

/**
 * 未知异常
 * 其他未预期的错误
 */
class UnknownException(override val message: String) : Exception(message)

9. MainActivity.kt - 使用示例

  • 作用:演示如何使用网络框架进行API请求。
  • 在网络链路中的位置:作为业务层,调用网络框架进行数据请求。
class MainActivity : AppCompatActivity() {
    /**
     * API服务实例
     * 通过RetrofitClient创建,用于调用具体的API接口
     */
    private val apiService: ApiService by lazy {
        RetrofitClient.createApiService(ApiService::class.java)
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        enableEdgeToEdge()
        setContentView(R.layout.activity_main)
        ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main)) { v, insets ->
            val systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars())
            v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom)
            insets
        }

        // 演示完整的网络请求流程
        demonstrateCompleteFlow()
    }

    /**
     * 演示完整的网络请求流程
     * 包含:登录、设置Token、获取用户信息、获取用户列表、并发请求、错误处理
     */
    private fun demonstrateCompleteFlow() {
        lifecycleScope.launch {
            Log.d("NetworkDemo", "========== 开始演示完整流程 ==========")

            // 步骤1: 用户登录
            Log.d("NetworkDemo", "\n步骤1: 用户登录")
            loginDemo()

            // 步骤2: 获取用户信息(带Token)
            Log.d("NetworkDemo", "\n步骤2: 获取用户信息")
            getUserInfoDemo()

            // 步骤3: 获取用户列表
            Log.d("NetworkDemo", "\n步骤3: 获取用户列表")
            getUserListDemo()

            // 步骤4: 并发请求演示
            Log.d("NetworkDemo", "\n步骤4: 并发请求演示")
            concurrentRequestsDemo()

            // 步骤5: 错误处理演示
            Log.d("NetworkDemo", "\n步骤5: 错误处理演示")
            errorHandlingDemo()

            // 步骤6: 清除Token
            Log.d("NetworkDemo", "\n步骤6: 清除Token")
            clearTokenDemo()

            Log.d("NetworkDemo", "========== 流程演示结束 ==========")
        }
    }

    /**
     * 步骤1: 用户登录演示
     * 展示如何调用登录接口并处理返回的Token
     */
    private suspend fun loginDemo() {
        val result = safeApiCall {
            apiService.login(
                username = "testuser",
                password = "password123"
            )
        }

        result
            .onLoading {
                Log.d("NetworkDemo", "登录中...")
            }
            .onSuccess { loginResponse ->
                Log.d("NetworkDemo", "登录成功!")
                Log.d("NetworkDemo", "Token: ${loginResponse.token}")
                Log.d("NetworkDemo", "用户信息: ${loginResponse.userInfo}")

                // 登录成功后设置Token,后续请求会自动携带
                RetrofitClient.setToken(loginResponse.token)
                Log.d("NetworkDemo", "Token已设置,后续请求将自动携带")
            }
            .onError { exception ->
                Log.e("NetworkDemo", "登录失败: ${exception.message}")
            }
    }

    /**
     * 步骤2: 获取用户信息演示
     * 展示如何使用Token进行认证请求
     */
    private suspend fun getUserInfoDemo() {
        val result = safeApiCall {
            apiService.getUserInfo()
        }

        result
            .onLoading {
                Log.d("NetworkDemo", "获取用户信息中...")
            }
            .onSuccess { userInfo ->
                Log.d("NetworkDemo", "获取用户信息成功!")
                Log.d("NetworkDemo", "用户ID: ${userInfo.id}")
                Log.d("NetworkDemo", "用户名: ${userInfo.username}")
                Log.d("NetworkDemo", "邮箱: ${userInfo.email}")
                Log.d("NetworkDemo", "头像: ${userInfo.avatar ?: "无"}")
            }
            .onError { exception ->
                Log.e("NetworkDemo", "获取用户信息失败: ${exception.message}")
            }
    }

    /**
     * 步骤3: 获取用户列表演示
     * 展示如何处理列表数据和分页参数
     */
    private suspend fun getUserListDemo() {
        val result = safeApiCall {
            apiService.getUserList(page = 1, size = 10)
        }

        result
            .onLoading {
                Log.d("NetworkDemo", "获取用户列表中...")
            }
            .onSuccess { userList ->
                Log.d("NetworkDemo", "获取用户列表成功!")
                Log.d("NetworkDemo", "用户数量: ${userList.size}")
                userList.forEachIndexed { index, user ->
                    Log.d("NetworkDemo", "  ${index + 1}. ${user.username} (${user.email})")
                }
            }
            .onError { exception ->
                Log.e("NetworkDemo", "获取用户列表失败: ${exception.message}")
            }
    }

    /**
     * 步骤4: 并发请求演示
     * 展示如何使用async/await同时发起多个请求
     */
    private suspend fun concurrentRequestsDemo() {
        Log.d("NetworkDemo", "同时发起多个请求...")

        // 使用async并发执行多个请求
        val userInfoDeferred = async {
            Log.d("NetworkDemo", "  请求1: 获取用户信息")
            safeApiCall { apiService.getUserInfo() }
        }

        val userListDeferred = async {
            Log.d("NetworkDemo", "  请求2: 获取用户列表")
            safeApiCall { apiService.getUserList(page = 1, size = 5) }
        }

        // 等待所有请求完成
        val userInfoResult = userInfoDeferred.await()
        val userListResult = userListDeferred.await()

        Log.d("NetworkDemo", "所有请求已完成")

        // 处理第一个请求的结果
        userInfoResult
            .onSuccess { userInfo ->
                Log.d("NetworkDemo", "请求1成功: ${userInfo.username}")
            }
            .onError { exception ->
                Log.e("NetworkDemo", "请求1失败: ${exception.message}")
            }

        // 处理第二个请求的结果
        userListResult
            .onSuccess { userList ->
                Log.d("NetworkDemo", "请求2成功: 获取到${userList.size}个用户")
            }
            .onError { exception ->
                Log.e("NetworkDemo", "请求2失败: ${exception.message}")
            }
    }

    /**
     * 步骤5: 错误处理演示
     * 展示如何处理各种异常情况
     */
    private suspend fun errorHandlingDemo() {
        Log.d("NetworkDemo", "演示错误处理...")

        // 模拟网络错误(这里只是演示,实际会调用真实API)
        val result = safeApiCall {
            apiService.getUserInfo()
        }

        result
            .onLoading {
                Log.d("NetworkDemo", "请求中...")
            }
            .onSuccess { userInfo ->
                Log.d("NetworkDemo", "请求成功: ${userInfo.username}")
            }
            .onError { exception ->
                Log.e("NetworkDemo", "请求失败")
                Log.e("NetworkDemo", "异常类型: ${exception.javaClass.simpleName}")
                Log.e("NetworkDemo", "错误信息: ${exception.message}")

                // 根据不同的异常类型进行不同的处理
                when (exception) {
                    is com.zzzjian.networkdemo.network.NetworkException -> {
                        Log.e("NetworkDemo", "网络异常,请检查网络连接")
                    }
                    is com.zzzjian.networkdemo.network.ApiException -> {
                        Log.e("NetworkDemo", "API异常,错误码: ${(exception as com.zzzjian.networkdemo.network.ApiException).code}")
                    }
                    else -> {
                        Log.e("NetworkDemo", "未知异常")
                    }
                }
            }
    }

    /**
     * 步骤6: 清除Token演示
     * 展示如何清除Token(用于登出场景)
     */
    private fun clearTokenDemo() {
        Log.d("NetworkDemo", "清除Token...")
        RetrofitClient.clearToken()
        Log.d("NetworkDemo", "Token已清除,后续请求将不再携带认证信息")
    }
}

4.网络请求完整链路

┌─────────────────────────────────────────────────────────────────┐
│                        业务层 (MainActivity)                     │
│                                                                 │
│  lifecycleScope.launch {                                        │
│      val result = safeApiCall { apiService.getUserInfo() }      │
│      result.onSuccess { ... }.onError { ... }                   │
│  }                                                              │
└────────────────────────────┬────────────────────────────────────┘
                             │
                             ▼
┌─────────────────────────────────────────────────────────────────┐
│              请求扩展层 (RequestExtensions.kt)                   │
│                                                                 │
│  safeApiCall()                                                  │
│  ├─ withContext(Dispatchers.IO)  // 切换到IO线程                │
│  ├─ try { apiCall() }            // 执行API调用                 │
│  ├─ 处理BaseResponse              // 转换为Result               │
│  └─ catch异常并转换               // 统一异常处理               │
└────────────────────────────┬────────────────────────────────────┘
                             │
                             ▼
┌─────────────────────────────────────────────────────────────────┐
│                 API接口层 (ApiService.kt)                        │
│                                                                 │
│  @GET("user/info")                                              │
│  suspend fun getUserInfo(): BaseResponse<UserInfo>              │
└────────────────────────────┬────────────────────────────────────┘
                             │
                             ▼
┌─────────────────────────────────────────────────────────────────┐
│              Retrofit客户端层 (RetrofitClient.kt)                │
│                                                                 │
│  Retrofit.create(ApiService::class.java)                        │
│  └─ 动态代理生成API接口实现                                      │
└────────────────────────────┬────────────────────────────────────┘
                             │
                             ▼
┌─────────────────────────────────────────────────────────────────┐
│                 OkHttp拦截器链 (按顺序执行)                      │
│                                                                 │
│  1. TokenInterceptor    // 添加Token到请求头                    │2. LogInterceptor      // 打印请求日志                         │3. CacheInterceptor    // 添加缓存策略                         │
└────────────────────────────┬────────────────────────────────────┘
                             │
                             ▼
┌─────────────────────────────────────────────────────────────────┐
│                    OkHttp网络层                                  │
│                                                                 │
│  ├─ 连接池管理                                                   │
│  ├─ 请求发送                                                     │
│  ├─ 响应接收                                                     │
│  └─ 自动重试                                                     │
└────────────────────────────┬────────────────────────────────────┘
                             │
                             ▼
┌─────────────────────────────────────────────────────────────────┐
│                      服务器                                      │
│                                                                 │
│  处理请求并返回JSON数据                                          │
└────────────────────────────┬────────────────────────────────────┘
                             │
                             ▼
┌─────────────────────────────────────────────────────────────────┐
│                 响应处理流程 (反向执行)                          │
│                                                                 │
│  1. CacheInterceptor    // 添加缓存控制头                       │2. LogInterceptor      // 打印响应日志                         │3. Gson转换器          // JSON → BaseResponse                   │4. safeApiCall         // BaseResponse → Result                │5. 业务层处理          // Result.onSuccess/onError              │
└─────────────────────────────────────────────────────────────────┘

5.详细请求步骤

1. 业务层发起请求

lifecycleScope.launch {
    val result = safeApiCall {
        apiService.getUserInfo()
    }
    result.onSuccess { ... }.onError { ... }
}

2. safeApiCall处理

  • 切换到IO线程
  • 执行API调用
  • 捕获异常并转换
  • 将BaseResponse转换为Result

3. Retrofit执行

  • 通过动态代理调用API接口方法
  • 构建HTTP请求
  • 调用OkHttp发送请求

4. OkHttp拦截器链(请求阶段)

  1. TokenInterceptor - 添加Authorization头
  2. LogInterceptor - 打印请求信息
  3. CacheInterceptor - 检查缓存(如果有)

5. 网络传输

  • OkHttp发送HTTP请求
  • 服务器处理并返回响应

6. OkHttp拦截器链(响应阶段)

  1. CacheInterceptor - 添加缓存控制头
  2. LogInterceptor - 打印响应信息

7. 响应处理

  • Gson将JSON转换为BaseResponse
  • safeApiCall将BaseResponse转换为Result
  • 业务层通过扩展函数处理Result

6.架构设计原则

1. 单一职责原则

每个类只负责一个功能:

  • BaseResponse - 响应格式定义
  • Result - 结果状态封装
  • 各Interceptor - 独立的拦截功能

2. 开闭原则

  • 通过拦截器扩展功能,无需修改核心代码
  • 新增API只需在ApiService中添加方法

3. 依赖倒置原则

  • 业务层依赖抽象的ApiService接口
  • 不直接依赖具体的网络实现

4. 接口隔离原则

  • ApiService只定义需要的接口方法
  • Result提供简洁的扩展函数接口

ok,复制粘贴完了,这个黄金网络架构组合是AI生成的,我想我到时候被裁了也不会找到应用层的岗位了,AI可以做的比我好,不管是界面还原,还是架构设计...

未来到底是个什么样的时代,AI可以做到哪一步?