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
相关产品推荐
相关产品推荐

