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

Kotlin应用开发报错:String?与String类型不匹配问题求解

解决Kotlin类型不匹配错误:String? 无法传入String参数

错误详情

  • 报错信息:

    "Type mismatch: inferred type is String? but String is expected"

  • 错误位置:DetailActivity中的viewModel.setPenggunaDetail(username)代码行,username由intent.getStringExtra(EXTRA_USERNAME)从MainActivity传递获取。

相关源码

DetailActivity代码

package com.example.submission2.Activity
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider
import com.bumptech.glide.Glide
import com.bumptech.glide.load.resource.drawable.DrawableTransitionOptions
import com.example.submission2.Adapter.AdapterSectionPager
import com.example.submission2.ViewModel.DetailVM
import com.example.submission2.databinding.ActivityDetailBinding

class DetailActivity : AppCompatActivity() {

    companion object{
        const val EXTRA_USERNAME = "extra_username"
    }

    private lateinit var binding: ActivityDetailBinding
    private lateinit var viewModel: DetailVM

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = ActivityDetailBinding.inflate(layoutInflater)
        setContentView(binding.root)
        supportActionBar?.apply {
            setDisplayHomeAsUpEnabled(true)
            setDisplayShowHomeEnabled(true)
        }
        val username = intent.getStringExtra(EXTRA_USERNAME)

        viewModel = ViewModelProvider(this, ViewModelProvider.NewInstanceFactory()).get(DetailVM::class.java)

        viewModel.setPenggunaDetail(username)
        viewModel.getPenggunaDetail().observe(this) {
            if (it != null) {
                binding.apply {
                    tvNamaDetail.text = it.name
                    tvUsernameDetail.text = it.login
                    tvCompanyDetail.text = it.company
                    tvEmailDetail.text = it.email
                    tvFollowersDetail.text = "${it.followers} Followers"
                    tvFollowingDetail.text = "${it.following} Follwing"
                    Glide.with(this@DetailActivity)
                        .load(it.avatar_url)
                        .transition(DrawableTransitionOptions.withCrossFade())
                        .centerCrop()
                        .into(ivDetailProfil)
                }
            }
        }
        val sectionPagerAdpter = AdapterSectionPager(this,supportFragmentManager)
        binding.apply {
            viewPager.adapter = sectionPagerAdpter
            tabs.setupWithViewPager(viewPager)
        }
    }
}

MainActivity代码

package com.example.submission2.Activity

import android.content.Intent
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.view.KeyEvent
import android.view.View
import androidx.lifecycle.ViewModelProvider
import androidx.recyclerview.widget.LinearLayoutManager
import com.example.submission2.Adapter.AdapterPengguna
import com.example.submission2.DataBase.Pengguna
import com.example.submission2.R
import com.example.submission2.ViewModel.MainVM
import com.example.submission2.databinding.ActivityMainBinding

class MainActivity : AppCompatActivity() {

    private lateinit var binding: ActivityMainBinding
    private lateinit var viewModel: MainVM
    private lateinit var adapter: AdapterPengguna

    private fun searchPengguna(){
        binding.apply {
            val query = etSearch.text.toString()
            if (query.isEmpty())return
            showLoading(true)
            viewModel.setSearchPengguna(query)
        }
    }

    private fun showLoading(state: Boolean){
        if (state){
            binding.progressBarMain.visibility = View.VISIBLE
        }else{
            binding.progressBarMain.visibility = View.GONE
        }
    }

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

        adapter = AdapterPengguna()
        adapter.notifyDataSetChanged()
        adapter.setOnItemClickCallback(object :AdapterPengguna.OnItemClickCallback{
            override fun onItemCliked(data: Pengguna) {
                Intent(this@MainActivity,DetailActivity::class.java).also {
                    it.putExtra(DetailActivity.EXTRA_USERNAME, data.login)
                    startActivity(it)
                }
            }
        })

        viewModel = ViewModelProvider(this,ViewModelProvider.NewInstanceFactory()).get(MainVM::class.java)

        binding.apply {
            rvPengguna.layoutManager = LinearLayoutManager(this@MainActivity)
            rvPengguna.setHasFixedSize(true)
            rvPengguna.adapter = adapter

            btnSearch.setOnClickListener {
                searchPengguna()
            }

            etSearch.setOnKeyListener { v, keyCode, event ->
                if (event.action == KeyEvent.ACTION_DOWN && keyCode == KeyEvent.KEYCODE_ENTER){
                    searchPengguna()
                    return@setOnKeyListener true
                }
                return@setOnKeyListener false
            }
        }
        viewModel.getSearchPengguna().observe(this,{
            if (it!= null){
                adapter.setList(it)
                showLoading(false)
            }
        })
    }
}

错误原因

  • intent.getStringExtra()返回可空类型String?:系统无法保证该Extra一定存在,所以返回值可能为空。
  • viewModel.setPenggunaDetail()方法的参数要求不可空的String类型,两者类型不匹配导致编译错误。

解决方案

方法1:强制非空(仅确定参数必传时使用)

在username后添加!!,强制告诉编译器该值不为空:

viewModel.setPenggunaDetail(username!!)

⚠️ 风险:如果username实际为空,会触发NullPointerException,仅在确认MainActivity一定会传递参数时使用。

方法2:设置默认值(避免空值)

用Elvis运算符?:给空值设置默认字符串:

viewModel.setPenggunaDetail(username ?: "default_user")

方法3:提前做空值校验(推荐)

先判断username是否为空,为空时处理异常逻辑(比如提示用户或返回上页),非空时再调用方法:

val username = intent.getStringExtra(EXTRA_USERNAME)
if (username == null) {
    Toast.makeText(this, "用户名参数缺失", Toast.LENGTH_SHORT).show()
    finish()
    return
}
// 此时username已被智能转换为非空String
viewModel.setPenggunaDetail(username)

方法4:修改ViewModel参数为可空类型(更符合Kotlin空安全)

如果业务逻辑允许接受空值,直接修改DetailVM中的方法定义:

// 在DetailVM类中修改方法
fun setPenggunaDetail(username: String?) {
    // 内部处理空值逻辑,比如跳过请求或提示错误
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.17 02:20:37