Spinner Listener LiveData 问题
Spinner Listener LiveData Issue
在我的 Fragment 中,我有两个微调器。
两者都由在 ViewModel 中观察到的 LiveData 填充,如下所示:
// Observe Filtered ProductGroups and populate Spinner
businessViewModel.filteredAppDataProductGroups.observe(viewLifecycleOwner, { productGroupArrayList ->
if (!productGroupArrayList.isNullOrEmpty()){
val adapter = ArrayAdapter(requireContext(), android.R.layout.simple_spinner_dropdown_item, productGroupArrayList)
binding.inventoryAddEditProductGroupSpinner.adapter = adapter
}
})
// Observe Filtered ProductTypes and populate Spinner
businessViewModel.filteredAppDataProductTypes.observe(viewLifecycleOwner, { productTypeArrayList ->
if (productTypeArrayList != null){
val adapter = ArrayAdapter(requireContext(), android.R.layout.simple_spinner_dropdown_item, productTypeArrayList)
binding.inventoryAddEditProductTypeSpinner.adapter = adapter
}
})
这工作正常,但我正在尝试根据第一个 Spinner 的当前选择过滤第二个 Spinner 中的数据,方法是设置侦听器并更新 ViewModel 数据,如下所示:
binding.inventoryAddEditProductGroupSpinner.onItemSelectedListener = object: AdapterView.OnItemSelectedListener{
override fun onItemSelected(parent:AdapterView<*>, view: View, position: Int, id: Long){
val productGroupObject = parent.selectedItem as ProductGroupObject
if (productGroupObject.productGroupID.isNotEmpty()){
businessViewModel.updateCurrentProductGroupVMLiveData(productGroupObject.productGroupID)
}
}
override fun onNothingSelected(parent: AdapterView<*>){
}
}
更新 ViewModel 中的过滤列表如下:
fun updateCurrentProductGroupVMLiveData (currentProductGroupId: String) {
val newProductGroup = allAppDataProductGroups.value?.find { productGroup -> productGroup.productGroupID == currentProductGroupId }
_currentProductGroup.value = newProductGroup
if(newProductGroup?.productGroup != null) {
val filteredProductsList = allAppDataProductTypes.value?.filter { productTypeObject -> productTypeObject.productGroup == newProductGroup.productGroup} as ArrayList<ProductTypeObject>
_filteredAppDataProductTypes.value = filteredProductsList
}
Log.d(TAG, "updateCurrentProductGroupVMLiveData(): '_currentProductGroupId.value' updated ($currentProductGroupId)")
}
但是,如果我将显示的代码添加到 onItemSelected 中,应用程序会崩溃并且我会看到以下错误:
--------- beginning of crash
2021-10-06 23:06:34.740 17510-17510/com.xxxxx.acorn E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.locators.acorn, PID: 17510
java.lang.NullPointerException: Parameter specified as non-null is null: method kotlin.jvm.internal.Intrinsics.checkNotNullParameter, parameter view
at com.xxxxx.acorn.business.inventory.InventoryAddEditFragment$setSpinnerListeners.onItemSelected(InventoryAddEditFragment.kt)
at android.widget.AdapterView.fireOnSelected(AdapterView.java:931)
at android.widget.AdapterView.dispatchOnItemSelected(AdapterView.java:920)
at android.widget.AdapterView.-wrap1(AdapterView.java)
at android.widget.AdapterView$SelectionNotifier.run(AdapterView.java:890)
at android.os.Handler.handleCallback(Handler.java:751)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:154)
at android.app.ActivityThread.main(ActivityThread.java:6077)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:866)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:756)
我看到 ViewModel 列表正在更改,所以我不知道为什么这会导致 NullPointerException。
错误日志似乎指向 view
(第 3 行)
java.lang.NullPointerException: Parameter specified as non-null is null: method kotlin.jvm.internal.Intrinsics.checkNotNullParameter, parameter view
我认为 parent: AdapterView<*>
和 view: View
是可空类型。
因此需要为该类型添加空安全调用运算符
binding.inventoryAddEditProductGroupSpinner.onItemSelectedListener = object: AdapterView.OnItemSelectedListener{
override fun onItemSelected(parent:AdapterView<*>?, view: View?, position: Int, id: Long){
...
}
override fun onNothingSelected(parent: AdapterView<*>?){
}
}
您可以简化和清理您的代码。
只需将所选位置传递给您的 viewmodel
override fun onItemSelected(parent:AdapterView<*>, view: View, position: Int, id: Long){
businessViewModel.updateCurrentProductGroup(position)
}
并在您的 viewmodel
class 中编写主要业务逻辑。像下面这样
fun updateCurrentProductGroup(position: Int){
// here you can do what you want
// example
val productGroupObject = filteredAppDataProductGroups.value[position]
if (productGroupObject.productGroupID.isNotEmpty()){
businessViewModel.updateCurrentProductGroupVMLiveData(productGroupObject.productGroupID)
}
}
在我的 Fragment 中,我有两个微调器。
两者都由在 ViewModel 中观察到的 LiveData 填充,如下所示:
// Observe Filtered ProductGroups and populate Spinner
businessViewModel.filteredAppDataProductGroups.observe(viewLifecycleOwner, { productGroupArrayList ->
if (!productGroupArrayList.isNullOrEmpty()){
val adapter = ArrayAdapter(requireContext(), android.R.layout.simple_spinner_dropdown_item, productGroupArrayList)
binding.inventoryAddEditProductGroupSpinner.adapter = adapter
}
})
// Observe Filtered ProductTypes and populate Spinner
businessViewModel.filteredAppDataProductTypes.observe(viewLifecycleOwner, { productTypeArrayList ->
if (productTypeArrayList != null){
val adapter = ArrayAdapter(requireContext(), android.R.layout.simple_spinner_dropdown_item, productTypeArrayList)
binding.inventoryAddEditProductTypeSpinner.adapter = adapter
}
})
这工作正常,但我正在尝试根据第一个 Spinner 的当前选择过滤第二个 Spinner 中的数据,方法是设置侦听器并更新 ViewModel 数据,如下所示:
binding.inventoryAddEditProductGroupSpinner.onItemSelectedListener = object: AdapterView.OnItemSelectedListener{
override fun onItemSelected(parent:AdapterView<*>, view: View, position: Int, id: Long){
val productGroupObject = parent.selectedItem as ProductGroupObject
if (productGroupObject.productGroupID.isNotEmpty()){
businessViewModel.updateCurrentProductGroupVMLiveData(productGroupObject.productGroupID)
}
}
override fun onNothingSelected(parent: AdapterView<*>){
}
}
更新 ViewModel 中的过滤列表如下:
fun updateCurrentProductGroupVMLiveData (currentProductGroupId: String) {
val newProductGroup = allAppDataProductGroups.value?.find { productGroup -> productGroup.productGroupID == currentProductGroupId }
_currentProductGroup.value = newProductGroup
if(newProductGroup?.productGroup != null) {
val filteredProductsList = allAppDataProductTypes.value?.filter { productTypeObject -> productTypeObject.productGroup == newProductGroup.productGroup} as ArrayList<ProductTypeObject>
_filteredAppDataProductTypes.value = filteredProductsList
}
Log.d(TAG, "updateCurrentProductGroupVMLiveData(): '_currentProductGroupId.value' updated ($currentProductGroupId)")
}
但是,如果我将显示的代码添加到 onItemSelected 中,应用程序会崩溃并且我会看到以下错误:
--------- beginning of crash
2021-10-06 23:06:34.740 17510-17510/com.xxxxx.acorn E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.locators.acorn, PID: 17510
java.lang.NullPointerException: Parameter specified as non-null is null: method kotlin.jvm.internal.Intrinsics.checkNotNullParameter, parameter view
at com.xxxxx.acorn.business.inventory.InventoryAddEditFragment$setSpinnerListeners.onItemSelected(InventoryAddEditFragment.kt)
at android.widget.AdapterView.fireOnSelected(AdapterView.java:931)
at android.widget.AdapterView.dispatchOnItemSelected(AdapterView.java:920)
at android.widget.AdapterView.-wrap1(AdapterView.java)
at android.widget.AdapterView$SelectionNotifier.run(AdapterView.java:890)
at android.os.Handler.handleCallback(Handler.java:751)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:154)
at android.app.ActivityThread.main(ActivityThread.java:6077)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:866)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:756)
我看到 ViewModel 列表正在更改,所以我不知道为什么这会导致 NullPointerException。
错误日志似乎指向 view
(第 3 行)
java.lang.NullPointerException: Parameter specified as non-null is null: method kotlin.jvm.internal.Intrinsics.checkNotNullParameter, parameter view
我认为 parent: AdapterView<*>
和 view: View
是可空类型。
因此需要为该类型添加空安全调用运算符
binding.inventoryAddEditProductGroupSpinner.onItemSelectedListener = object: AdapterView.OnItemSelectedListener{
override fun onItemSelected(parent:AdapterView<*>?, view: View?, position: Int, id: Long){
...
}
override fun onNothingSelected(parent: AdapterView<*>?){
}
}
您可以简化和清理您的代码。
只需将所选位置传递给您的 viewmodel
override fun onItemSelected(parent:AdapterView<*>, view: View, position: Int, id: Long){
businessViewModel.updateCurrentProductGroup(position)
}
并在您的 viewmodel
class 中编写主要业务逻辑。像下面这样
fun updateCurrentProductGroup(position: Int){
// here you can do what you want
// example
val productGroupObject = filteredAppDataProductGroups.value[position]
if (productGroupObject.productGroupID.isNotEmpty()){
businessViewModel.updateCurrentProductGroupVMLiveData(productGroupObject.productGroupID)
}
}