安卓Spinner使用问题:点击Button应用崩溃,请求技术支持与讲解
Hey there! Let's break this down step by step—first I'll explain what a Spinner is, then we'll fix that crash issue in your unit converter app.
A Spinner is a drop-down selection component in Android, similar to a dropdown menu. It displays the currently selected option by default, and when tapped, it shows a list of predefined choices (either as a dialog or a dropdown, based on the spinnerMode setting). When a user selects an option, it triggers a selection event that your app can respond to.
Looking at your code, there are a few key issues causing the crash and unexpected behavior:
- Repeatedly setting Button click listeners: Every time you select a new Spinner option, you're assigning a new
OnClickListenerto the Button. This leads to overlapping listeners and messy logic, which can cause crashes when the Button is tapped after switching options multiple times. - Invalid String formatting: Lines like
String.format("%.2f",result + " cm")are the direct cause of the crash. The%.2fformat specifier expects a floating-point number, but you're passing a string (e.g., "12.34 cm")—this throws anIllegalFormatConversionException. - Unnecessary app termination: Calling
exit(0)inonNothingSelectedis a bad practice; it abruptly kills the app instead of handling the situation gracefully.
We'll refactor the code to separate the Spinner selection logic from the Button click logic. We'll store the selected Spinner position, then use that position to run the correct conversion when the Button is tapped. This makes the code cleaner and avoids the crash.
Fixed MainActivity.java
package com.example.edward.converter; import android.graphics.Color; import android.os.Bundle; import android.support.v7.app.AppCompatActivity; import android.view.View; import android.widget.AdapterView; import android.widget.Button; import android.widget.EditText; import android.widget.Spinner; import android.widget.TextView; public class MainActivity extends AppCompatActivity { private Button btn; private TextView txt; private EditText etxt; private Spinner spn; // Store the currently selected Spinner position private int selectedPosition = 0; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); btn = findViewById(R.id.button); txt = findViewById(R.id.textView); etxt = findViewById(R.id.editText); spn = findViewById(R.id.spinner); // Spinner listener: only update the selected position spn.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { @Override public void onItemSelected(AdapterView<?> parent, View view, int position, long id) { selectedPosition = position; } @Override public void onNothingSelected(AdapterView<?> parent) { // Replace abrupt exit with a friendly message txt.setText("Please select a conversion type"); txt.setTextColor(Color.RED); txt.setVisibility(View.VISIBLE); } }); // Button listener: handle conversion based on selected position btn.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { String inputStr = etxt.getText().toString().trim(); // Check for empty input if(inputStr.isEmpty()){ txt.setText(R.string.error); txt.setTextColor(Color.RED); txt.setVisibility(View.VISIBLE); return; } double inputValue; try { // Handle non-numeric input to avoid crashes inputValue = Double.parseDouble(inputStr); } catch (NumberFormatException e) { txt.setText(R.string.error); txt.setTextColor(Color.RED); txt.setVisibility(View.VISIBLE); return; } double result = 0.0; String unit = ""; // Run conversion based on selected Spinner option switch (selectedPosition){ case 0 : // Inch-cm result = inputValue * 2.54; unit = " cm"; break; case 1 : // cm-Inch result = inputValue * 0.393701; unit = " Inch"; break; case 2 : // Inch-Metre result = inputValue * 0.0254; unit = " Metre"; break; case 3 : // Metre-Inch result = inputValue * 39.3701; // Fixed incorrect conversion factor unit = " Inch"; break; case 4 : // cm-Metre result = inputValue * 0.01; unit = " Metre"; break; case 5 : // Metre-cm result = inputValue * 100; unit = " cm"; break; } // Correct string formatting: format the number first, then add the unit txt.setText(String.format("%.2f", result) + unit); txt.setTextColor(Color.WHITE); txt.setVisibility(View.VISIBLE); } }); } }
Additional Improvements
- Fixed the incorrect conversion factor in case 3 (changed 39.9701 to the correct 39.3701)
- Added
NumberFormatExceptionhandling to prevent crashes from non-numeric input - Used
trim()on the input to handle accidental spaces - Removed the abrupt
exit(0)call and replaced it with a user-friendly message - Separated concerns for cleaner, more maintainable code
Now when you run the app, you can switch Spinner options, enter a value, and tap Convert to see the correct result without crashes.
内容的提问来源于stack exchange,提问作者Rahul Shah

