Spinner的NullPointerException问题-->未解决(初步怀疑是Spinner本身的问题)

本文详细解析了 Android 中 Spinner 控件出现 NullPointerException 的原因,并提供了解决方案,即在 DialogPopup 的 dismiss 方法中增加对 mPopup 是否为空的判断。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 java.lang.NullPointerException
//      at android.widget.Spinner$DialogPopup.dismiss(Spinner.java:907)
//      at android.widget.Spinner$DialogPopup.onClick(Spinner.java:945)
//      at com.android.internal.app.AlertController$AlertParams$3.onItemClick(Al
ertController.java:941)
//      at android.widget.AdapterView.performItemClick(AdapterView.java:298)
//      at android.widget.AbsListView.performItemClick(AbsListView.java:1100)
//      at android.widget.AbsListView$PerformClick.run(AbsListView.java:2788)
//      at android.widget.AbsListView$1.run(AbsListView.java:3463)
//      at android.widget.AbsListView.onDetachedFromWindow(AbsListView.java:2670
)
//      at android.view.View.dispatchDetachedFromWindow(View.java:12160)
//      at android.view.ViewGroup.dispatchDetachedFromWindow(ViewGroup.java:2570
)
//      at android.view.ViewGroup.dispatchDetachedFromWindow(ViewGroup.java:2568
)
//      at android.view.ViewGroup.dispatchDetachedFromWindow(ViewGroup.java:2568
)
//      at android.view.ViewGroup.dispatchDetachedFromWindow(ViewGroup.java:2568
)
//      at android.view.ViewGroup.dispatchDetachedFromWindow(ViewGroup.java:2568
)
//      at android.view.ViewGroup.dispatchDetachedFromWindow(ViewGroup.java:2568
)
//      at android.view.ViewRootImpl.dispatchDetachedFromWindow(ViewRootImpl.jav
a:2820)
//      at android.view.ViewRootImpl.doDie(ViewRootImpl.java:5164)
//      at android.view.ViewRootImpl$ViewRootHandler.handleMessage(ViewRootImpl.
java:3148)
//      at android.os.Handler.dispatchMessage(Handler.java:99)
//      at android.os.Looper.loop(Looper.java:137)
//      at android.app.ActivityThread.main(ActivityThread.java:5136)
//      at java.lang.reflect.Method.invokeNative(Native Method)
//      at java.lang.reflect.Method.invoke(Method.java:525)
//      at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit
.java:739)
//      at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:555)

//      at dalvik.system.NativeStart.main(Native Method)


在Spinner源代码中:

DialogPopup的dismiss()方法中加上判断mPopup是否为空

package com.example.kucun2.function; import android.content.Context; import android.util.Log; import android.view.View; import android.view.ViewGroup; import android.widget.ArrayAdapter; import android.widget.Spinner; import android.widget.TextView; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import com.example.kucun2.entity.Bancai; import com.example.kucun2.entity.Caizhi; import com.example.kucun2.entity.Chanpin; import com.example.kucun2.entity.Dingdan; import com.example.kucun2.entity.Mupi; import com.example.kucun2.entity.Zujian; import java.util.List; public class Adapter { // 安全适配器基类,处理公共逻辑 private static abstract class SafeSpinnerAdapter<T> extends ArrayAdapter<T> { private static final String TAG="AdapterAdapter"; public SafeSpinnerAdapter(Context context, int resource, List<T> objects) { super(context, resource, objects); } @Override public View getDropDownView(int position, @Nullable View convertView, @NonNull ViewGroup parent) { // 修复:确保视图不为null if (convertView == null) { convertView = super.getView(position, null, parent); } View view = super.getDropDownView(position, convertView, parent); TextView textView = view.findViewById(android.R.id.text1); T item = getItem(position); // 处理空对象 String text = (item != null) ? formatDropdownText(item) : "空项"; textView.setText(text); return view; } @NonNull @Override public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) { // 修复:确保视图不为null if (convertView == null) { convertView = super.getView(position, null, parent); } View view = super.getView(position, convertView, parent); TextView textView = view.findViewById(android.R.id.text1); T item = getItem(position); // 处理空对象 String text = (item != null) ? formatDisplayText(item) : "请选择"; textView.setText(text); return view; } // 在具体适配器中确保返回非空字符串 protected abstract String formatDisplayText(T item); protected abstract String formatDropdownText(T item); } // 1. 材质适配器 public static ArrayAdapter<Caizhi> setupCaizhiSpinner(Spinner spinner, List<Caizhi> data, Context context) { ArrayAdapter<Caizhi> adapter = new SafeSpinnerAdapter<Caizhi>(context, android.R.layout.simple_spinner_item, data) { @Override protected String formatDisplayText(Caizhi item) { return item != null ? item.getName() : "请选择材质"; } @Override protected String formatDropdownText(Caizhi item) { return item != null ? item.getName() : ""; } }; adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); spinner.setAdapter(adapter); return adapter; } // 2. 木皮适配器 public static void setupMupiSpinner(Spinner spinner, List<Mupi> data, Context context) { ArrayAdapter<Mupi> adapter = new SafeSpinnerAdapter<Mupi>(context, android.R.layout.simple_spinner_item, data) { @Override protected String formatDisplayText(Mupi item) { return item != null ? item.formatMupiDisplay() : "请选择木皮"; } @Override protected String formatDropdownText(Mupi item) { return item != null ? item.formatMupiDisplay() : ""; } }; adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); spinner.setAdapter(adapter); } // 3. 板材适配器 public static void setupBancaiSpinners(Spinner spinner, List<Bancai> data, Context context) { ArrayAdapter<Bancai> adapter = new SafeSpinnerAdapter<Bancai>(context, android.R.layout.simple_spinner_item, data) { @Override protected String formatDisplayText(Bancai item) { return item != null ? item.TableText() : "请选择板材"; } @Override protected String formatDropdownText(Bancai item) { return item != null ? item.TableText() : ""; } }; adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); spinner.setAdapter(adapter); } // 4. 订单适配器 public static void setupDingdanSpinner(Spinner spinner, List<Dingdan> data, Context context) { ArrayAdapter<Dingdan> adapter = new SafeSpinnerAdapter<Dingdan>(context, android.R.layout.simple_spinner_item, data) { @Override protected String formatDisplayText(Dingdan item) { return item != null ? item.getNumber() : "请选择"; } @Override protected String formatDropdownText(Dingdan item) { return item != null ? item.getNumber() : "请选择"; } }; adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); spinner.setAdapter(adapter); } // 5. 产品适配器 public static void setupChanpinSpinner(Spinner spinner, List<Chanpin> data, Context context) { ArrayAdapter<Chanpin> adapter = new SafeSpinnerAdapter<Chanpin>(context, android.R.layout.simple_spinner_item, data) { @Override protected String formatDisplayText(Chanpin item) { return item != null ? item.getBianhao() : "请选择"; } @Override protected String formatDropdownText(Chanpin item) { return item != null ? item.getBianhao() : "请选择"; } }; adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); spinner.setAdapter(adapter); } // 6. 组件适配器 public static void setupZujianSpinner(Spinner spinner, List<Zujian> data, Context context) { ArrayAdapter<Zujian> adapter = new SafeSpinnerAdapter<Zujian>(context, android.R.layout.simple_spinner_item, data) { @Override protected String formatDisplayText(Zujian item) { return item != null ? item.getName() : "请选择"; } @Override protected String formatDropdownText(Zujian item) { return item != null ? item.getName() : "请选择"; } }; adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); spinner.setAdapter(adapter); } } ViewGroup parent参数什么情况下是空?convertView什么情况下才为空? ----------------现在这两个一直为空
07-01
activity_main.xml中的 id 和MianActivity.java 中的 id 写的不照应,看不懂吗:package com.example.myapplication import androidx.appcompat.app.AppCompatActivity import android.os.Bundle import android.widget.ArrayAdapter import android.widget.Spinner import android.widget.TextView import android.widget.Toast import com.google.android.material.button.MaterialButton import com.google.android.material.textfield.TextInputEditText class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) // 初始化UI组件 val num1Input = findViewById<TextInputEditText>(R.id.editTextNumber1) val num2Input = findViewById<TextInputEditText>(R.id.editTextNumber2) val operatorSpinner = findViewById<Spinner>(R.id.spinnerOperator) val calculateBtn = findViewById<MaterialButton>(R.id.buttonCalculate) val resultText = findViewById<TextView>(R.id.textViewResult) // 配置Spinner适配器 val operators = resources.getStringArray(R.array.operators) val adapter = ArrayAdapter( this, android.R.layout.simple_spinner_item, operators ).apply { setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item) } operatorSpinner.adapter = adapter operatorSpinner.setSelection(0) // 默认选中第一个运算符 calculateBtn.setOnClickListener { // 获取输入值 val num1Str = num1Input.text.toString() val num2Str = num2Input.text.toString() val operator = operatorSpinner.selectedItem.toString() // 验证输入 if (num1Str.isEmpty() || num2Str.isEmpty()) { Toast.makeText(this, R.string.error_empty, Toast.LENGTH_SHORT).show() return@setOnClickListener } val num1 = num1Str.toDoubleOrNull() val num2 = num2Str.toDoubleOrNull() if (num1 == null || num2 == null) { Toast.makeText(this, R.string.error_invalid, Toast.LENGTH_SHORT).show() return@setOnClickListener } // 执行计算 val result = when (operator) { "+" -> num1 + num2 "-" -> num1 - num2 "*" -> num1 * num2 "/" -> { if (num2 == 0.0) { Toast.makeText(this, R.string.error_divide_zero, Toast.LENGTH_SHORT).show() return@setOnClickListener } num1 / num2 } else -> 0.0 } // 显示结果(保留两位小数) resultText.text = "%.2f".format(result) } } }<?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity"> <!-- 第一个数字输入框 --> <com.google.android.material.textfield.TextInputLayout android:id="@+id/textInputLayout1" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_marginStart="16dp" android:layout_marginTop="32dp" android:layout_marginEnd="16dp" app:boxBackgroundMode="outline" app:boxCornerRadiusTopStart="12dp" app:boxCornerRadiusTopEnd="12dp" app:boxStrokeColor="@color/purple_200" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent"> <com.google.android.material.textfield.TextInputEditText android:id="@+id/editTextNumber1" android:layout_width="match_parent" android:layout_height="wrap_content" android:hint="@string/hint_num1" android:inputType="numberDecimal" android:padding="8dp" android:textSize="16sp" /> </com.google.android.material.textfield.TextInputLayout> <!-- 第二个数字输入框 --> <com.google.android.material.textfield.TextInputLayout android:id="@+id/textInputLayout2" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_marginStart="16dp" android:layout_marginTop="16dp" android:layout_marginEnd="16dp" app:boxBackgroundMode="outline" app:boxCornerRadiusTopStart="12dp" app:boxCornerRadiusTopEnd="12dp" app:boxStrokeColor="@color/purple_200" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@id/textInputLayout1"> <com.google.android.material.textfield.TextInputEditText android:id="@+id/editTextNumber2" android:layout_width="match_parent" android:layout_height="wrap_content" android:hint="@string/hint_num2" android:inputType="numberDecimal" android:padding="8dp" android:textSize="16sp" /> </com.google.android.material.textfield.TextInputLayout> <!-- 运算符选择下拉菜单 --> <com.google.android.material.textfield.TextInputLayout android:id="@+id/textInputLayoutOperator" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_marginStart="16dp" android:layout_marginTop="16dp" android:layout_marginEnd="16dp" app:boxBackgroundMode="outline" app:boxCornerRadiusTopStart="12dp" app:boxCornerRadiusTopEnd="12dp" app:boxStrokeColor="@color/purple_200" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@id/textInputLayout2"> <com.google.android.material.textfield.MaterialAutoCompleteTextView android:id="@+id/spinnerOperator" android:layout_width="match_parent" android:layout_height="wrap_content" android:entries="@string/result_hint" android:inputType="none" android:padding="8dp" android:textSize="16sp" /> </com.google.android.material.textfield.TextInputLayout> <!-- 计算按钮 --> <com.google.android.material.button.MaterialButton android:id="@+id/buttonCalculate" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_marginStart="16dp" android:layout_marginTop="24dp" android:layout_marginEnd="16dp" android:text="@string/calculate" android:textColor="@android:color/white" android:textSize="16sp" app:backgroundTint="@color/purple_500" app:cornerRadius="12dp" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@id/textInputLayoutOperator" /> <!-- 结果显示 --> <TextView android:id="@+id/textViewResult" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_marginStart="16dp" android:layout_marginTop="24dp" android:layout_marginEnd="16dp" android:background="@color/purple_50" android:gravity="center" android:padding="12dp" android:text="@string/result_hint" android:textSize="20sp" android:textStyle="bold" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@id/buttonCalculate" /> </androidx.constraintlayout.widget.ConstraintLayout> 给我正确的两个文件
最新发布
07-29
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值