Kotlin 与 API:现代开发的三大支柱
\n\n您有没有想过,为什么有些应用程序运行如飞,而另一些即使在旗舰设备上也会卡顿?秘诀往往不在于硬件,而在于它们与服务器的通信方式。如果您正在使用 Kotlin 编写代码——无论是基于 Ktor 的后端还是 Android 应用程序——迟早您都会面临选择:REST、GraphQL 还是 gRPC?
\n\n在 PythonLib,我们喜欢深入剖析技术细节。今天,我们将系统地梳理三种 在 Kotlin 中使用 API 的方法。毫无水分:只有代码、对比和真实案例。开始吧!
\n\nKotlin 中的 REST API:永不褪色的经典
\n\nREST 就像一套黑色西装:在任何场合都适用,简单且易懂。在 Kotlin 中,REST 有两个主要参与者:Ktor(用于服务端)和 Retrofit(用于客户端)。
\n\n基于 Ktor 的服务端:5 分钟编写 API
\n\nKtor 是 JetBrains 专为 Kotlin 打造的框架。它异步、轻量,且不强制引入不必要的依赖。
\n\n// build.gradle.kts\nimplementation("io.ktor:ktor-server-netty:2.3.7")\nimplementation("io.ktor:ktor-server-content-negotiation:2.3.7")\nimplementation("io.ktor:ktor-serialization-kotlinx-json:2.3.7")\n\n现在来看服务端本身:
\n\nimport io.ktor.server.engine.*\nimport io.ktor.server.netty.*\nimport io.ktor.server.routing.*\nimport io.ktor.server.response.*\nimport io.ktor.serialization.kotlinx.json.*\nimport io.ktor.server.plugins.contentnegotiation.*\nimport kotlinx.serialization.Serializable\n\n@Serializable\ndata class User(val id: Int, val name: String, val email: String)\n\nfun main() {\n embeddedServer(Netty, port = 8080) {\n install(ContentNegotiation) {\n json()\n }\n routing {\n get("/api/users") {\n val users = listOf(\n User(1, "安娜", "anna@example.com"),\n User(2, "鲍里斯", "boris@example.com")\n )\n call.respond(users)\n }\n get("/api/users/{id}") {\n val id = call.parameters["id"]?.toIntOrNull()\n if (id != null) {\n call.respond(User(id, "测试", "test@example.com"))\n } else {\n call.respondText("无效 ID", status = io.ktor.http.HttpStatusCode.BadRequest)\n }\n }\n }\n }.start(wait = true)\n}\n\n这段代码是一个包含两个端点的完整 Kotlin REST API。Ktor 通过 kotlinx.serialization 自动将数据序列化为 JSON。
基于 Retrofit 的客户端:连接到任意 API
\n\nRetrofit 是 Android 开发的事实标准。得益于协程,它与 Kotlin 配合得天衣无缝。
\n\n// build.gradle.kts\nimplementation("com.squareup.retrofit2:retrofit:2.9.0")\nimplementation("com.squareup.retrofit2:converter-gson:2.9.0")\nimplementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.7.3")\n\n声明接口:
\n\ninterface ApiService {\n @GET("users")\n suspend fun getUsers(): List<User>\n\n @GET("users/{id}")\n suspend fun getUser(@Path("id") userId: Int): User\n\n @POST("users")\n suspend fun createUser(@Body user: User): User\n}\n\n创建客户端并发送请求:
\n\nval retrofit = Retrofit.Builder()\n .baseUrl("https://api.example.com/")\n .addConverterFactory(GsonConverterFactory.create())\n .build()\n\nval service = retrofit.create(ApiService::class.java)\n\n// 在协程中\nGlobalScope.launch {\n val users = service.getUsers()\n println(users)\n}\n\nREST 的优点: 简单、支持 HTTP 缓存、社区庞大。
\n缺点: 数据过度获取(over-fetching)和获取不足(under-fetching)——您经常得到比需要更多或更少的数据。