凌峰创科服务平台

Android如何解析服务器返回的JSON数据?

  1. 网络请求:在 Android 设备上向服务器发送一个 HTTP 请求。
  2. 服务器响应:服务器处理请求,并返回一个包含 JSON 数据的 HTTP 响应。
  3. 解析 JSON:从 HTTP 响应中提取 JSON 字符串,并将其解析成 Android 可以使用的对象(如 ListMap 或自定义的 Java/Kotlin 数据类)。
  4. 更新 UI:将解析后的数据展示在用户界面上。

第一步:准备工作(非常重要)

在开始写代码之前,必须完成以下设置,否则应用无法进行网络请求。

Android如何解析服务器返回的JSON数据?-图1
(图片来源网络,侵删)

添加网络权限

app/src/main/AndroidManifest.xml 文件中,为你的应用添加访问网络的权限。

<!-- 允许应用打开网络套接字 -->
<uses-permission android:name="android.permission.INTERNET" />
<!-- 如果你的应用使用的是 Android 9 (API 28) 或更高版本,默认情况下不允许 HTTP (非 HTTPS),
     如果你的服务器只支持 HTTP,需要添加以下配置,强烈建议使用 HTTPS。 -->
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />

处理网络线程问题(关键!)

Android 的主线程(UI 线程)不允许执行耗时操作,网络请求就是典型的耗时操作,如果在主线程中发起网络请求,你的应用会抛出 NetworkOnMainThreadException 异常并崩溃。

解决方案: 使用异步任务来执行网络请求,在 Android 中,有几种主流方式:

  • Kotlin 协程Google 官方推荐 的方式,代码简洁,易于管理异步任务。
  • Retrofit + OkHttp:业界标准的网络请求库,Retrofit 负责将 API 接口定义和调用转化为具体的网络请求,OkHttp 负责执行请求,它们内部也使用了协程或回调来处理线程切换。
  • 传统 AsyncTask:已废弃,不推荐在新项目中使用。

第二步:选择技术栈并实现

下面我将展示三种主流的实现方式,从简单到强大,推荐使用 方式二(Retrofit + 协程)

Android如何解析服务器返回的JSON数据?-图2
(图片来源网络,侵删)

使用 HttpURLConnection(原生,不推荐用于生产)

这是 Android SDK 自带的网络 API,无需添加第三方库,但使用起来比较繁琐。

场景:快速原型验证,或者不想引入第三方库时。

步骤:

  1. 创建一个协程作用域 来发起网络请求,避免阻塞主线程。
  2. 发起 GET 请求
  3. 读取输入流,将响应数据转换成字符串。
  4. 解析 JSON 字符串
  5. 返回结果并在主线程更新 UI。

示例代码 (Kotlin):

Android如何解析服务器返回的JSON数据?-图3
(图片来源网络,侵删)

假设我们有一个简单的 JSON API:https://jsonplaceholder.typicode.com/posts/1

返回的 JSON 数据:

{
  "userId": 1,
  "id": 1,: "sunt aut facere repellat provident occaecati excepturi optio reprehenderit",
  "body": "quia et suscipit\nsuscipit recusandae consequuntur expedita et cum\nreprehenderit molestiae ut ut quas totam\nnostrum rerum est autem sunt rem eveniet architecto"
}
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.util.Log
import android.widget.TextView
import android.widget.Toast
import kotlinx.coroutines.*
import java.io.BufferedReader
import java.io.InputStreamReader
import java.net.HttpURLConnection
import java.net.URL
class MainActivity : AppCompatActivity() {
    private lateinit var tvResult: TextView
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        tvResult = findViewById(R.id.tv_result)
        // 在协程作用域内发起网络请求
        CoroutineScope(Dispatchers.IO).launch {
            val data = fetchDataFromServer()
            // 切换回主线程更新 UI
            withContext(Dispatchers.Main) {
                tvResult.text = data
            }
        }
    }
    private suspend fun fetchDataFromServer(): String {
        return withContext(Dispatchers.IO) {
            var urlConnection: HttpURLConnection? = null
            return@withContext try {
                val url = URL("https://jsonplaceholder.typicode.com/posts/1")
                urlConnection = url.openConnection() as HttpURLConnection
                urlConnection.requestMethod = "GET"
                urlConnection.connectTimeout = 15000
                urlConnection.readTimeout = 15000
                val responseCode = urlConnection.responseCode
                if (responseCode == HttpURLConnection.HTTP_OK) {
                    val inputStream = urlConnection.inputStream
                    val reader = BufferedReader(InputStreamReader(inputStream))
                    val response = StringBuilder()
                    var line: String?
                    while (reader.readLine().also { line = it } != null) {
                        response.append(line)
                    }
                    reader.close()
                    inputStream.close()
                    response.toString() // 返回 JSON 字符串
                } else {
                    "Error: HTTP $responseCode"
                }
            } catch (e: Exception) {
                Log.e("MainActivity", "Error fetching data", e)
                "Error: ${e.message}"
            } finally {
                urlConnection?.disconnect()
            }
        }
    }
}

使用 Retrofit + OkHttp + Kotlin 协程(强烈推荐)

这是目前最流行、最强大的方案,它将网络请求、JSON 解析和线程管理完美地封装起来,让你的代码非常简洁和可维护。

步骤:

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

    // Retrofit
    implementation 'com.squareup.retrofit2:retrofit:2.9.0'
    implementation 'com.squareup.retrofit2:converter-gson:2.9.0' // JSON 解析器
    implementation 'com.squareup.okhttp3:logging-interceptor:4.9.3' // OkHttp 日志拦截器(可选,用于调试)
    // 协程
    implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.4'
    implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.6.4'
  2. 定义数据模型: 根据 JSON 结构创建一个 Kotlin 数据类。

    // Post.kt
    data class Post(
        val userId: Int,
        val id: Int,
        val title: String,
        val body: String
    )
  3. 创建 Retrofit 实例和 API 接口

    // ApiService.kt
    import retrofit2.http.GET
    interface ApiService {
        @GET("posts/1")
        suspend fun getPost(): Post // 使用 suspend 关键字,使其可以在协程中直接调用
    }
  4. 在 Activity/ViewModel 中调用 API 并更新 UI

    import androidx.appcompat.app.AppCompatActivity
    import android.os.Bundle
    import android.widget.TextView
    import retrofit2.Retrofit
    import retrofit2.converter.gson.GsonConverterFactory
    class MainActivity : AppCompatActivity() {
        private lateinit var tvResult: TextView
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            setContentView(R.layout.activity_main)
            tvResult = findViewById(R.id.tv_result)
            // 初始化 Retrofit
            val retrofit = Retrofit.Builder()
                .baseUrl("https://jsonplaceholder.typicode.com/")
                .addConverterFactory(GsonConverterFactory.create())
                .build()
            // 创建 API 服务的实例
            val apiService = retrofit.create(ApiService::class.java)
            // 在协程中发起网络请求
            CoroutineScope(Dispatchers.Main).launch {
                try {
                    val post = apiService.getPost()
                    tvResult.text = "Title: ${post.title}\n\nBody: ${post.body}"
                } catch (e: Exception) {
                    tvResult.text = "Failed to fetch data: ${e.message}"
                    e.printStackTrace()
                }
            }
        }
    }

优点

  • 代码简洁:API 接口定义清晰,调用方式同步,无需处理回调地狱。
  • 类型安全:编译时就能检查 API 接口定义是否正确。
  • 可扩展性强:轻松支持请求体、查询参数、文件上传等复杂场景。
  • 生态完善:有大量社区支持的拦截器(如日志、认证)。

使用 Volley(Google 官方提供的库)

Volley 是 Google 推出的一个网络通信库,特别适合数据量不大、但通信频繁的场景(如加载图片、JSON 数据)。

步骤:

  1. 添加依赖: 在 app/build.gradle 中:

    implementation 'com.android.volley:volley:1.2.1'
  2. 在 Activity 中使用

    import androidx.appcompat.app.AppCompatActivity
分享:
扫描分享到社交APP
上一篇
下一篇