从类中获取可为空的 var
Posted
技术标签:
【中文标题】从类中获取可为空的 var【英文标题】:Get a nullable var from a class 【发布时间】:2020-04-14 17:12:57 【问题描述】:首先让我说我的 Kotlin 经验有限。我试图从一个类中获取一个可以为空的var
,但是每当我执行它时都会得到一个空指针。
类代码:
class MultiSpinner : Spinner, OnMultiChoiceClickListener, OnCancelListener
private var items: List<String>? = null
private var selected: BooleanArray? = null
private var selectedNew: BooleanArray? = null
private var defaultText: String? = null
private var listener: MultiSpinnerListener? = null
var category: String = "010"
constructor(context: Context) : super(context)
constructor(arg0: Context, arg1: AttributeSet) : super(arg0, arg1)
constructor(arg0: Context, arg1: AttributeSet, arg2: Int) : super(arg0, arg1, arg2)
override fun onClick(dialog: DialogInterface, which: Int, isChecked: Boolean)
selectedNew!![which] = isChecked
override fun onCancel(dialog: DialogInterface)
// refresh text on spinner
val spinnerBuffer = StringBuffer()
var allUnselected = true
for (i in items!!.indices)
if (selected!![i])
spinnerBuffer.append(items!![i])
spinnerBuffer.append(", ")
allUnselected = false
selectedNew!![i] = selected!![i]
var spinnerText: String?
if (allUnselected)
spinnerText = defaultText
else
spinnerText = spinnerBuffer.toString()
/** Remove trailing comma*/
spinnerText = spinnerText.substring(0, spinnerText.length - 2)
val adapter = ArrayAdapter(
context,
R.layout.simple_spinner_item,
arrayOf(spinnerText)
)
setAdapter(adapter)
category = selected!!.joinToString(limit = selected!!.size, separator = "") it.toInt().toString()
listener!!.onItemsSelected(selected)
override fun performClick(): Boolean
val builder = AlertDialog.Builder(context)
builder.setMultiChoiceItems(
items!!.toTypedArray(), selectedNew, this
)
builder.setPositiveButton(R.string.ok
) dialog, _ -> selected = selectedNew!!.copyOf(); dialog.cancel()
builder.setNegativeButton(R.string.cancel
) dialog, _ -> dialog.cancel()
builder.setOnCancelListener(this)
builder.show()
return true
fun setItems(
items: List<String>, allText: String,
listener: MultiSpinnerListener
)
this.items = items
this.defaultText = allText
this.listener = listener
// one selected by default
selected = BooleanArray(items.size) false
selectedNew = BooleanArray(items.size) false
for (i in selected!!.indices)
selected!![i] = false
selectedNew!![i] = false
selected!![0] = true
selectedNew!![0] = true
category = selected!!.joinToString(limit = selected!!.size, separator = "") it.toInt().toString()
// all text on the spinner
val adapter = ArrayAdapter(
context,
R.layout.simple_spinner_item, arrayOf(allText)
)
setAdapter(adapter)
fun getSelected(): BooleanArray?
return selected
interface MultiSpinnerListener
fun onItemsSelected(selected: BooleanArray?)
private fun Boolean.toInt() = if (this) 1 else 0
正在初始化
override fun onCreate(savedInstanceState: Bundle?)
...
val spinnerCategory: MultiSpinner = findViewById(R.id.category_spinner)
val categoryList: List<String> = resources.getStringArray(R.array.category).toList()
spinnerCategory.setItems(categoryList, getString(R.string.default_category), this)
...
从MultiSpinner
访问selected
val selected: BooleanArray? = MultiSpinner(this).getSelected()
println(selected)
println 读取null
。
我已经尝试返回 BooleanArray
而不是 BooleanArray?
来返回 getSelected
,但这只是给了我一个空指针异常(正如 println 读数所预期的那样)。
我现在通过在类中使用category
并在类中执行操作来规避这个问题。但是,我想在我的主要活动中获取selected
数组,并使用它的数据在类之外创建我想要的字符串。
为什么我没有得到我的selected
数据,而是一个空指针?
【问题讨论】:
您的getSelected()
呼叫在哪里? onCreate
也有吗?
现在只看到你的评论,它在onCreate
之外的另一个函数中使用
【参考方案1】:
您必须使用从findViewById
获得的实例(视图层次结构中已经存在的实例)访问selected
,而不是自己创建一个全新的对象:
val selected: BooleanArray? = spinnerCategory.getSelected()
编辑:
如果您需要在onCreate
方法之外访问selected
,只需将spinnerCategory
存储为属性而不是局部变量:
private lateinit var spinnerCategory: MultiSpinner
override fun onCreate(savedInstanceState: Bundle?)
spinnerCategory = findViewById(R.id.category_spinner)
...
Kotlin 还为 android 提供了一个不错的功能,称为 View Binding,它允许您省略调用 findViewById
并直接使用它们的 id 引用您的视图:
override fun onCreate(savedInstanceState: Bundle?)
...
category_spinner.setItems(categoryList, getString(R.string.default_category), this)
...
private fun doSomethingWithSelected()
val selected: BooleanArray? = category_spinner.getSelected()
但是在这种情况下我建议更改视图的 id,使其符合 Kotlin 变量命名准则,例如到spinnerCategory
,因为它已经被使用了。
【讨论】:
当spinnerCategory
在onCreate()
的作用域末尾被销毁时,我将如何访问它?
@NSimons 我在回答中添加了一些额外的信息。
谢谢,我暂时使用了你的第一个建议,等我有时间再研究一下视图绑定【参考方案2】:
您使用null
初始化了selected
,这意味着它可以为空,因此编译器认为您可能会在此参数中获得空值。
如果您不希望它为 null,您可以像这样定义变量:
private var selected: BooleanArray = false
现在selected
参数在任何时候都不能为空。
【讨论】:
问题不在于它是否可以包含null
,而在于为什么我得到null
在这种情况下,您需要访问spinnerCategory
,因为该对象是在onCreate
方法中创建的。如果你想从你应该做的方法之外访问它:var spinnerCategory: MultiSpinner override fun onCreate(savedInstanceState: Bundle?) ... spinnerCategory: = findViewById(R.id.category_spinner) val categoryList: List<String> = resources.getStringArray(R.array.category).toList() spinnerCategory.setItems(categoryList, getString(R.string.default_category), this) ...
谢谢,这行得通(有一些补充)。使用 private lateinit var spinnerCategory: MultiSpinner
成功了。以上是关于从类中获取可为空的 var的主要内容,如果未能解决你的问题,请参考以下文章
为啥 TargetNullValue 更新可为空的 Source
检查JSON var是否具有可为空的密钥(Twitter Streaming API)