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

Java迁移Kotlin后Spinner适配器报非空参数为null的NPE问题

问题原因

你遇到的空指针异常是Kotlin与Java互操作时空安全声明不匹配导致的:

  • BaseAdapter是Java编写的Android框架类,其定义的getView、getDropDownView方法中,用于视图复用的convertView参数是可空类型:列表首次渲染、没有可复用视图时,系统会传入null,要求适配器自行加载布局。
  • 迁移后的Kotlin代码将这两个方法的复用视图参数声明为非空View类型,Kotlin编译器会自动在方法入口插入非空校验,系统传入null时就会直接抛出你看到的Intrinsics.checkNotNullParameter异常。

除此之外代码还有几个会触发运行时错误的隐患:

  • getItem方法的返回值在父类中是可空类型,声明为非空Any还使用TODO占位,调用到该方法时会直接抛出未实现异常。
  • roundCorners方法中直接将parent.parent强转为View,没有做非空判断,父级类型不匹配或为null时会触发类型转换异常。
  • 构造函数中Context参数声明为可空,和实际调用时传入非空Activity的场景不匹配,存在空安全隐患。
修复方案

按照以下步骤调整代码,和原Java逻辑保持完全一致即可解决异常:

  • 调整getView、getDropDownView的方法签名,将复用视图参数声明为可空View?,和父类方法签名对齐。
  • 修正getItem方法,将返回值改为可空Any?,直接返回null和原Java逻辑对齐,删除TODO占位。
  • 修正roundCorners方法的类型强转逻辑,使用安全类型转换,保留原Java的非空判断逻辑。
  • 调整构造函数参数,将Context声明为非空类型,移除不必要的临时参数映射。
修正后的完整适配器代码
import android.content.Context
import android.graphics.Color
import android.graphics.drawable.GradientDrawable
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.BaseAdapter
import android.widget.TextView

// 替换为你自己项目对应类的包路径即可
internal class CustomSubjectSpinnerAdapter(
    applicationContext: Context,
    private val subjectOptions: Array<String>
) : BaseAdapter() {
    private val inflter: LayoutInflater = LayoutInflater.from(applicationContext)

    override fun getCount(): Int {
        return subjectOptions.size
    }

    override fun getItem(i: Int): Any? {
        return null
    }

    override fun getItemId(i: Int): Long {
        return 0
    }

    override fun getDropDownView(position: Int, convertView: View?, parent: ViewGroup): View {
        var realConvertView = convertView
        if (realConvertView == null) {
            val vi = parent.context.getSystemService(Context.LAYOUT_INFLATER_SERVICE) as LayoutInflater
            realConvertView = vi.inflate(R.layout.subject_spinner_row, null)
        }
        val llLayout = super.getDropDownView(position, realConvertView, parent)
        roundCorners(parent)
        return llLayout
    }

    private fun roundCorners(parent: ViewGroup) {
        val container2Round = parent.parent as? View
        if (container2Round != null) {
            val gd = GradientDrawable(
                GradientDrawable.Orientation.TOP_BOTTOM,
                intArrayOf(Color.WHITE, Color.WHITE)
            )
            val radius = AWScreen.dp2px(10)
            gd.cornerRadius = radius.toFloat()
            container2Round.background = gd
        }
    }

    override fun getView(i: Int, view: View?, viewGroup: ViewGroup): View {
        // 保留原Java每次inflate新布局的逻辑,和原有行为完全一致
        val itemView = inflter.inflate(R.layout.subject_spinner_row, null)
        val tvSubject = itemView.findViewById<TextView>(R.id.subject)
        tvSubject.text = subjectOptions[i]
        if (subjectOptions[i] == "") {
            tvSubject.visibility = View.GONE
        }
        setListItemRoundedCorners(tvSubject, i)
        if (i == subjectOptions.size - 1) {
            val padding = AWScreen.sp2px(10f, itemView.context)
            tvSubject.setPadding(padding, padding, padding, padding)
        }
        return itemView
    }

    private fun setListItemRoundedCorners(tvSubject: TextView, i: Int) {
        if (i == 1) {
            tvSubject.setBackgroundResource(R.drawable.rounded_border_top)
        } else if (i == 2) {
            tvSubject.setBackgroundResource(R.drawable.rounded_border_bottom)
        }
    }
}

注:上述代码完全保留了原Java版本的逻辑(包括每次getView重新inflate布局、圆角设置逻辑、返回值逻辑),不会改变原有UI表现,仅修复了Kotlin互操作导致的空指针问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.30 17:03:33