凌峰创科服务平台

android post 服务器

核心概念:POST 请求

在开始编码前,我们先简单理解一下 POST 请求:

android post 服务器-图1
(图片来源网络,侵删)
  • 用途:用于向服务器提交数据,通常用于创建新资源(如注册用户、发布文章)或更新已有资源。
  • 数据位置:数据可以放在请求体中,而不是像 GET 请求那样放在 URL 里,这使得 POST 可以发送大量数据,并且数据对用户是不可见的。
  • 安全性:相比 GET,POST 更安全,因为它不会将敏感数据暴露在 URL 或服务器日志中(但数据本身仍然需要加密,如使用 HTTPS)。

现代推荐 - 使用 Retrofit + OkHttp (业界标准)

对于任何新项目,强烈推荐使用 Retrofit,它是一个类型安全的 HTTP 客户端,由 Square 公司(就是那个做 ButterKnife 的公司)开发,它将网络请求简化为简单的 Java/Kotlin 接口调用,非常优雅和高效。

Retrofit 内部默认使用 OkHttp 来处理底层的网络连接。

添加依赖

在你的 app/build.gradle.kts (或 build.gradle) 文件中添加依赖:

// build.gradle.kts (Kotlin DSL)
dependencies {
    // Retrofit: 用于定义和执行 API 接口
    implementation("com.squareup.retrofit2:retrofit:2.9.0")
    // Gson: 用于 JSON 数据的序列化与反序列化
    implementation("com.squareup.retrofit2:converter-gson:2.9.0")
    // OkHttp: 网络请求的底层实现
    implementation("com.squareup.okhttp3:okhttp:4.11.0")
    // Coroutines: 用于异步处理,推荐与 Retrofit 配合使用
    implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.7.3")
}

添加网络权限

app/src/main/AndroidManifest.xml 中添加网络权限:

android post 服务器-图2
(图片来源网络,侵删)
<manifest ...>
    <uses-permission android:name="android.permission.INTERNET" />
    <application ...>
        ...
    </application>
</manifest>

创建数据模型

创建一个 Kotlin 数据类来映射服务器返回的 JSON 数据。

// User.kt
data class User(
    val id: Int,
    val name: String,
    val email: String
)
// API 响应的通用结构(如果服务器返回的是这种格式)
data class ApiResponse<T>(
    val code: Int,
    val message: String,
    val data: T
)

定义 API 接口

创建一个接口,用注解来描述你的 API 端点。

// ApiService.kt
import retrofit2.Call
import retrofit2.http.*
interface ApiService {
    // 发送 JSON 数据
    @POST("api/users")
    suspend fun createUser(
        @Body user: User // @Body 注解表示将 user 对象作为 JSON 放入请求体
    ): User // suspend 关键字使其可以在协程中直接调用,无需手动处理 Call
    // 发送表单数据 (application/x-www-form-urlencoded)
    @POST("api/login")
    suspend fun login(
        @Field("username") username: String,
        @Field("password") password: String
    ): User
    // 发送键值对 (multipart/form-data),适合上传文件
    @Multipart
    @POST("api/upload")
    suspend fun uploadFile(
        @Part("file") file: okhttp3.MultipartBody.Part,
        @Part("description") description: RequestBody
    ): String
}

创建 Retrofit 实例并调用

// ApiClient.kt
import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory
object ApiClient {
    private const val BASE_URL = "https://your-api-server.com/" // 替换为你的服务器地址
    val instance: ApiService by lazy {
        val retrofit = Retrofit.Builder()
            .baseUrl(BASE_URL)
            .addConverterFactory(GsonConverterFactory.create())
            .build()
        retrofit.create(ApiService::class.java)
    }
}

在 Activity/ViewModel 中使用 (协程方式)

这是最推荐的异步调用方式,代码简洁且易于管理。

// MainActivity.kt
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.widget.Button
import android.widget.Toast
import kotlinx.coroutines.*
class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        val btnPost = findViewById<Button>(R.id.btn_post)
        btnPost.setOnClickListener {
            // 在协程作用域中执行网络请求
            CoroutineScope(Dispatchers.IO).launch {
                try {
                    // 1. 准备数据
                    val newUser = User(name = "John Doe", email = "john.doe@example.com")
                    // 2. 调用 API
                    val response = ApiClient.instance.createUser(newUser)
                    // 3. 切换到主线程更新 UI
                    withContext(Dispatchers.Main) {
                        Toast.makeText(this@MainActivity, "创建用户成功: ${response.name}", Toast.LENGTH_SHORT).show()
                    }
                } catch (e: Exception) {
                    // 4. 处理错误
                    withContext(Dispatchers.Main) {
                        Toast.makeText(this@MainActivity, "请求失败: ${e.message}", Toast.LENGTH_SHORT).show()
                    }
                }
            }
        }
    }
}

传统方式 - 使用 OkHttp 直接发送请求

如果你不想引入 Retrofit,或者只是想做一个简单的请求,可以直接使用 OkHttp。

android post 服务器-图3
(图片来源网络,侵删)

添加依赖

同上,需要 okhttpokhttp-tls (如果需要 HTTPS)。

发送 POST 请求示例

import okhttp3.*
import java.io.IOException
// 创建 OkHttp 客户端
val client = OkHttpClient()
// 准备请求体 (JSON 格式)
val mediaType = MediaType.Companion.parse("application/json; charset=utf-8")
val jsonBody = """{"name": "Jane Doe", "email": "jane.doe@example.com"}"""
val body = RequestBody.Companion.create(mediaType, jsonBody)
// 构建请求
val request = Request.Builder()
    .url("https://your-api-server.com/api/users") // 替换为你的 URL
    .post(body) // 指定 POST 请求并设置请求体
    .build()
// 发送请求 (同步方式,会阻塞线程,不推荐在主线程使用)
try {
    val response = client.newCall(request).execute()
    if (response.isSuccessful) {
        val responseBody = response.body?.string()
        println("响应成功: $responseBody")
    } else {
        println("请求失败: ${response.code}")
    }
} catch (e: IOException) {
    e.printStackTrace()
}
// 发送请求 (异步方式,推荐)
client.newCall(request).enqueue(object : Callback {
    override fun onFailure(call: Call, e: IOException) {
        // 请求失败
        e.printStackTrace()
    }
    override fun onResponse(call: Call, response: Response) {
        // 请求成功
        if (response.isSuccessful) {
            val responseBody = response.body?.string()
            // 注意:这里不能直接更新 UI,需要切换到主线程
            println("响应成功: $responseBody")
        } else {
            println("请求失败: ${response.code}")
        }
    }
})

最佳实践与注意事项

  1. 永远不要在主线程执行网络请求 Android 的主线程(UI 线程)负责处理用户界面交互,如果在主线程进行网络请求,会导致应用无响应(ANR - Application Not Responding)。

    • 解决方案:使用 Thread + HandlerAsyncTask(已废弃)、ExecutorService,或者更现代的 Kotlin CoroutinesRxJava,Retrofit + Coroutines 是目前最优雅的组合。
  2. 处理网络状态 在发送请求前,最好检查一下网络是否可用。

    fun isNetworkAvailable(context: Context): Boolean {
        val connectivityManager = context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            val activeNetwork = connectivityManager.activeNetwork
            val caps = connectivityManager.getNetworkCapabilities(activeNetwork)
            return caps != null && (caps.hasTransport(NetworkCapabilities.TRANSPORT_WIFI) || caps.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR))
        } else {
            // 对于旧版本 API
            val networkInfo = connectivityManager.activeNetworkInfo
            return networkInfo != null && networkInfo.isConnected
        }
    }
  3. 安全性:使用 HTTPS 在生产环境中,必须使用 HTTPS 协议来加密数据传输,防止中间人攻击和数据泄露,OkHttp 和 Retrofit 都默认支持 HTTPS。

  4. 错误处理 网络请求可能因为各种原因失败:无网络、服务器宕机、服务器返回 4xx/5xx 错误、JSON 解析失败等,代码中必须有完善的错误处理机制。

  5. 数据序列化

    • JSON:推荐使用 MoshiGson,Moshi 是 Square 公司推出的,性能更好,并且对 Kotlin 支持更友好。
    • Protobuf:如果对性能要求极高,可以使用 Protocol Buffers。
方法 优点 缺点 适用场景
Retrofit + OkHttp 类型安全、代码简洁、功能强大(支持协程/RxJava)、可扩展性好、社区活跃 引入了第三方库,有一定学习成本 所有新项目,尤其是复杂应用
OkHttp 直接请求 轻量级,无需额外抽象,适合简单、一次性的请求 代码冗余,手动处理线程、JSON 转换等,不易维护 简单工具、快速原型、学习网络基础

对于绝大多数 Android 学习和使用 Retrofit 是必不可少的技能,它能让你从繁琐的网络细节中解放出来,专注于业务逻辑。

分享:
扫描分享到社交APP
上一篇
下一篇