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

使用Retrofit2+RxJava2解析Gson时lateinit未初始化致RecyclerView数据异常

解决Retrofit2+RxJava2中UninitializedPropertyAccessException及RecyclerView数据不显示问题

嘿,我来帮你搞定这个问题!首先,导致你遇到UninitializedPropertyAccessException(提示lateinit property data has not been initialized)的直接原因非常明确,咱们先从这个核心错误入手:

核心错误:传错了参数到displayData方法

在fetchData方法的订阅回调里,你写的是:

.subscribe ({ companyList-> displayData(data) },{ ... })

这里的data是你在Activity里声明的lateinit var data : List<Company>,但这个变量自始至终都没有被赋值过!你应该把回调返回的companyList传给displayData才对,也就是改成:

.subscribe ({ companyList-> displayData(companyList) },{ ... })

而且这个data变量其实完全是多余的,直接删掉它就好,避免后续混淆。

其他需要修复的问题

除了核心错误,你的代码里还有几个坑会导致RecyclerView无法正常显示数据甚至崩溃:

1. CompanyAdapter里遗留的TODO注释

Adapter的onCreateViewHolder、getItemCount、onBindViewHolder方法里都有TODO("not implemented"),这行代码会直接抛出NotImplementedError,必须删掉,保留实际的业务代码。比如onCreateViewHolder应该改成:

override fun onCreateViewHolder(p0: ViewGroup, p1: Int): CompanyViewHolder {
    val itemView = LayoutInflater.from(p0.context).inflate(R.layout.list_view_item,p0,false)
    return CompanyViewHolder(itemView)
}

2. getItemCount里的冗余非空断言

你的Adapter构造函数里companyList是不可空的List<Company>,所以getItemCount里直接返回companyList.size就行,不用companyList?.size!!这种多余的写法:

override fun getItemCount(): Int {
    return companyList.size
}

3. RecyclerView LayoutManager的不必要强转

在showCompanyPopupView里,设置LayoutManager的时候不需要强转,直接写:

rvCompany.layoutManager = LinearLayoutManager(this)

LinearLayoutManager本身就是RecyclerView.LayoutManager的子类,强转完全没必要。

4. 避免内存泄漏:清理CompositeDisposable

记得在Activity的onDestroy方法里清理CompositeDisposable,防止RxJava订阅导致的内存泄漏:

override fun onDestroy() {
    super.onDestroy()
    compositeDisposable.dispose()
}

5. 修复Activity类名冲突

你的Activity类名居然叫Company,这和你的数据类重名了,会导致混淆,建议改成CompanyActivity:

class CompanyActivity : AppCompatActivity() { ... }

6. 处理Retrofit为空的情况

在fetchData里,如果APIClient.apIClient返回null,api这个lateinit变量会未初始化,建议加个判断:

private fun fetchData(){
    val retrofit = APIClient.apIClient ?: run {
        Toast.makeText(applicationContext, "初始化Retrofit失败", Toast.LENGTH_SHORT).show()
        return
    }
    api = retrofit.create(APIInterface::class.java)
    // 后续订阅代码...
}

修正后的关键代码片段

CompanyActivity.kt(原MainActivity.kt改名后)

class CompanyActivity : AppCompatActivity() {
    internal lateinit var api : APIInterface
    val compositeDisposable = CompositeDisposable()
    internal lateinit var companyDialog : Dialog
    internal lateinit var adapter: CompanyAdapter
    internal lateinit var rvCompany : RecyclerView

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_company)
        companyDialog = Dialog(this)
        btnSelectCompany.setOnClickListener{
            showCompanyPopupView()
        }
    }

    fun showCompanyPopupView(){
        companyDialog.setContentView(R.layout.compny_popup_screen)
        rvCompany = companyDialog.findViewById(R.id.rvCompany)
        rvCompany.setHasFixedSize(true)
        rvCompany.layoutManager = LinearLayoutManager(this)
        fetchData()
        companyDialog.window.setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT))
        companyDialog.show()
    }

    private fun fetchData(){
        val retrofit = APIClient.apIClient ?: run {
            Toast.makeText(applicationContext, "Retrofit初始化失败", Toast.LENGTH_SHORT).show()
            return
        }
        api = retrofit.create(APIInterface::class.java)
        
        compositeDisposable.add(api.getCompanyData()
            .subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe ({ companyList-> 
                displayData(companyList) 
            },{
                Toast.makeText(applicationContext, it.message, Toast.LENGTH_SHORT).show()
            })
        )
    }

    private fun displayData(companyList: List<Company>) {
        adapter = CompanyAdapter(this,companyList)
        rvCompany.adapter = adapter
    }

    override fun onDestroy() {
        super.onDestroy()
        compositeDisposable.dispose()
    }
}

CompanyAdapter.kt

class CompanyAdapter(internal var context: Context, internal var companyList: List<Company>) :RecyclerView.Adapter<CompanyAdapter.CompanyViewHolder>() {
    override fun onCreateViewHolder(p0: ViewGroup, p1: Int): CompanyViewHolder {
        val itemView = LayoutInflater.from(p0.context).inflate(R.layout.list_view_item,p0,false)
        return CompanyViewHolder(itemView)
    }

    override fun getItemCount(): Int {
        return companyList.size
    }

    override fun onBindViewHolder(p0: CompanyViewHolder, p1: Int) {
        p0.bindModel(companyList[p1])
    }

    inner class CompanyViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView){
        val radioButton : RadioButton = itemView.findViewById(R.id.rbCompanyName)
        fun bindModel(company: Company){
            radioButton.text = company.Cmp_Name
        }
    }
}

把这些修改都做完,你的代码应该就能正常请求数据并显示在RecyclerView里了。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.12 04:52:25