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

点击部分宝可梦详情页触发NullPointerException崩溃问题求助

解决宝可梦详情页偶发空指针崩溃问题

让我帮你分析下这个问题——从错误日志和代码来看,你遇到的空指针异常根源其实很明确:

错误日志里的核心报错是:

java.lang.NullPointerException: Attempt to invoke interface method 'java.lang.Object java.util.List.get(int)' on a null object reference

这说明你在调用List.get(int)的时候,这个List本身是null。对应到你的代码里,就是pokemon.abilities[0].name这一行——你的pokemon.abilities字段为null,当你尝试获取第一个元素时就触发了崩溃,而且这是偶发的,说明只有部分宝可梦的这个字段没有被正确初始化。

问题出在哪?

看你的configDetalhes()方法,你发起了详情接口请求,但在observe回调里完全没有使用接口返回的详情数据,反而直接用了导航参数传递过来的pokemon对象。这个导航参数里的pokemon大概率是从列表页传过来的简略数据,可能只包含了部分字段(比如名字、ID),而abilities字段要么是null,要么部分宝可梦的这个字段是空列表,导致调用[0]时崩溃。

修复方案

我给你几个递进的修复步骤:

  1. 紧急修复:给abilities字段加空安全判断
    在直接访问abilities[0]之前,必须先判断列表是否存在且不为空,用Kotlin的空安全语法可以轻松实现:

    private fun configDetalhes() {
        detalhesViewModel.getDetalhes(pokemon.id)
        detalhesViewModel.mResponse.observe(viewLifecycleOwner, {
            if (it.isSuccessful) {
                tv_detalhes_nome_pokemon.text = pokemon.nome
                // 空安全处理abilities字段
                val abilityName = pokemon.abilities?.takeIf { it.isNotEmpty() }?.get(0)?.name ?: "无能力"
                tv_detalhes_habilidades_pokemon.text = abilityName
                tv_hp_detalhes_pokemon.text = pokemon.hp
            }
        })
    }
    
  2. 逻辑修正:使用详情接口返回的完整数据
    既然你发起了详情接口请求,为什么不用返回的完整数据呢?导航参数里的pokemon只是简略数据,详情接口应该返回更完整的宝可梦信息,这也能从根源避免数据不全的问题:

    private fun configDetalhes() {
        detalhesViewModel.getDetalhes(pokemon.id)
        detalhesViewModel.mResponse.observe(viewLifecycleOwner, { response ->
            if (response.isSuccessful) {
                // 先判断body是否不为null
                val pokemonDetail = response.body() ?: return@observe
                tv_detalhes_nome_pokemon.text = pokemonDetail.nome
                // 同样做空安全处理
                val abilityName = pokemonDetail.abilities?.takeIf { it.isNotEmpty() }?.get(0)?.name ?: "无能力"
                tv_detalhes_habilidades_pokemon.text = abilityName
                // 如果hp是Int类型,记得转成String
                tv_hp_detalhes_pokemon.text = pokemonDetail.hp.toString()
            } else {
                // 别忘了处理请求失败的情况,比如显示错误提示
                Toast.makeText(context, "获取详情失败", Toast.LENGTH_SHORT).show()
            }
        })
    }
    
  3. 数据解析检查
    还要确保你的PokemonItem数据类在解析接口返回的JSON时,abilities字段被正确映射。比如如果接口返回的abilities是null或者空数组,你的数据类应该把它解析成List<Ability>?或者emptyList(),而不是默认的null。举个例子:

    data class PokemonItem(
        val nome: String,
        val hp: Int,
        val abilities: List<Ability>? = emptyList() // 给个默认空列表,避免null
    )
    
    data class Ability(val name: String)
    

额外建议

  • 永远不要假设列表类型的字段一定不为null且不为空,尤其是从接口返回的数据,一定要做空安全判断。
  • 可以在ViewModel里对返回的数据做预处理,比如把null的列表转换成空列表,这样UI层就不用重复做判断了。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.29 12:58:11