You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android用Retrofit+View Binding获取嵌套JSON数组适配RecyclerView

Android端Retrofit拉取嵌套JSON+ViewBinding+RecyclerView完整实现

以下实现基于Kotlin + 协程编写,Java开发逻辑完全对齐,仅存在语法差异。我们先约定待解析的嵌套JSON结构示例(实际开发替换为你的接口返回结构即可):

{
  "code": 0,
  "message": "请求成功",
  "data": [
    {
      "article_id": 1001,
      "title": "Android 开发入门",
      "author": "张三",
      "tags": ["移动端", "Kotlin", "入门教程"] // 嵌套的JSON数组
    },
    {
      "article_id": 1002,
      "title": "Retrofit 源码解析",
      "author": "李四",
      "tags": ["开源库", "源码", "网络请求"]
    }
  ]
}

1. 前置依赖与配置

在Module级别的build.gradle文件中添加依赖,同时开启ViewBinding:

android {
    // ... 其他已有配置
    buildFeatures {
        viewBinding true // 开启ViewBinding
    }
}

dependencies {
    // RecyclerView控件
    implementation "androidx.recyclerview:recyclerview:1.3.2"
    // Retrofit 核心库
    implementation "com.squareup.retrofit2:retrofit:2.9.0"
    // Gson 转换器,自动解析JSON为实体类
    implementation "com.squareup.retrofit2:converter-gson:2.9.0"
    // 协程依赖,用于异步发起网络请求
    implementation "androidx.lifecycle:lifecycle-runtime-ktx:2.6.2"
}

在AndroidManifest.xml中添加网络权限:

<uses-permission android:name="android.permission.INTERNET" />

2. 定义对应嵌套结构的实体类

根据JSON结构编写Kotlin数据类,Gson会自动递归解析嵌套的数组/对象,不需要手动处理嵌套层级:

// 列表项实体类,对应data数组里的每个元素
data class ArticleItem(
    @SerializedName("article_id") val id: Int,
    @SerializedName("title") val title: String,
    @SerializedName("author") val author: String,
    @SerializedName("tags") val tags: List<String> // 直接映射嵌套的JSON数组
)

// 接口最外层返回实体
data class ApiResponse(
    @SerializedName("code") val code: Int,
    @SerializedName("message") val msg: String,
    @SerializedName("data") val articleList: List<ArticleItem> // 外层嵌套的JSON数组
)

3. 配置Retrofit接口与实例

首先定义网络请求接口:

interface ArticleApiService {
    @GET("article/list") // 替换为你的接口实际路径
    suspend fun getArticleList(): ApiResponse
}

编写Retrofit单例实例,避免重复创建资源浪费:

object RetrofitClient {
    // 替换为你的接口实际baseUrl,注意必须以/结尾
    private const val BASE_URL = "https://your-api-domain.com/"

    val apiService: ArticleApiService by lazy {
        Retrofit.Builder()
            .baseUrl(BASE_URL)
            .addConverterFactory(GsonConverterFactory.create())
            .build()
            .create(ArticleApiService::class.java)
    }
}

4. 编写RecyclerView列表适配器

适配器直接使用item布局生成的ViewBinding类,完全避免手写findViewById:
首先写列表item的布局item_article.xml,放置文本控件展示标题、作者、标签即可:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical"
    android:padding="16dp">
    <TextView
        android:id="@+id/tv_title"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textSize="18sp"
        android:textStyle="bold"/>
    <TextView
        android:id="@+id/tv_author"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="4dp"
        android:textSize="14sp"/>
    <TextView
        android:id="@+id/tv_tags"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="4dp"
        android:textSize="12sp"/>
</LinearLayout>

然后编写适配器代码:

class ArticleAdapter : RecyclerView.Adapter<ArticleAdapter.ArticleViewHolder>() {

    private var dataList: List<ArticleItem> = emptyList()

    // 刷新列表数据
    fun submitList(list: List<ArticleItem>) {
        dataList = list
        notifyDataSetChanged()
    }

    inner class ArticleViewHolder(val binding: ItemArticleBinding) : RecyclerView.ViewHolder(binding.root)

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ArticleViewHolder {
        val binding = ItemArticleBinding.inflate(LayoutInflater.from(parent.context), parent, false)
        return ArticleViewHolder(binding)
    }

    override fun onBindViewHolder(holder: ArticleViewHolder, position: Int) {
        val item = dataList[position]
        with(holder.binding) {
            tvTitle.text = item.title
            tvAuthor.text = "作者:${item.author}"
            // 处理嵌套的标签数组,拼接成字符串展示
            tvTags.text = "标签:${item.tags.joinToString("、")}"
        }
    }

    override fun getItemCount(): Int = dataList.size
}

5. Activity中完成最终逻辑串联

主布局activity_main.xml中放置RecyclerView控件即可:

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/rv_article"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>
</FrameLayout>

在MainActivity中完成初始化、请求、数据加载逻辑:

class MainActivity : AppCompatActivity() {
    // ViewBinding实例
    private lateinit var binding: ActivityMainBinding
    private lateinit var articleAdapter: ArticleAdapter

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = ActivityMainBinding.inflate(layoutInflater)
        setContentView(binding.root)

        // 初始化RecyclerView
        articleAdapter = ArticleAdapter()
        binding.rvArticle.apply {
            layoutManager = LinearLayoutManager(this@MainActivity)
            adapter = articleAdapter
        }

        // 发起网络请求拉取数据
        lifecycleScope.launch {
            runCatching {
                RetrofitClient.apiService.getArticleList()
            }.onSuccess { response ->
                if (response.code == 0) {
                    // 请求成功,把嵌套数组里的数据提交给适配器展示
                    articleAdapter.submitList(response.articleList)
                }
            }.onFailure {
                // 这里处理请求失败逻辑,比如弹Toast提示
                it.printStackTrace()
            }
        }
    }
}

注意事项

  • Retrofit的baseUrl必须以/结尾,否则会抛出IllegalArgumentException
  • 嵌套JSON解析失败时,先通过日志打印原始返回内容,核对字段名、字段类型是否和实体类匹配
  • RecyclerView必须设置LayoutManager,否则列表不会渲染
  • 不要在主线程发起网络请求,使用协程或Retrofit自带的enqueue异步方法即可避免ANR
  • 如果targetSdkVersion >= 28,默认禁止明文HTTP请求,接口是HTTP的需要额外配置网络安全规则

内容的提问来源于stack exchange,提问作者Ravi_Makani

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.28 10:01:08