Avatar ·

Приложение вылетает с ошибкой "Unfortunately MyApp has stopped". Как исправить?

Всем привет. Я новичок в Android-разработке на Java. Создал простое приложение — калькулятор с двумя полями ввода и кнопкой "Сложить". При запуске на эмуляторе всё работает, но на реальном телефоне (Android 9) при нажатии на кнопку приложение вылетает с сообщением "Unfortunately MyApp has stopped". Вот мой код в MainActivity.java: ```java public class MainActivity extends AppCompatActivity { EditText num1, num2; Button addBtn; TextView result; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); num1 = findViewById(R.id.num1); num2 = findViewById(R.id.num2); addBtn = findViewById(R.id.addBtn); result = findViewById(R.id.result); addBtn.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { int a = Integer.parseInt(num1.getText().toString()); int b = Integer.parseInt(num2.getText().toString()); result.setText("Сумма: " + (a + b)); } }); } } ``` Я проверил, что все ID в layout-файле правильные. Приложение крашится сразу после нажатия на кнопку, даже если поля пустые. Что я делаю не так? Как найти причину падения и исправить? Буду благодарен за подробное объяснение, так как только начинаю. <<>>

Причина проблемы

Ваша ошибка — классический случай необработанного исключения (uncaught exception), которое возникает из-за вызова Integer.parseInt() на пустой строке или строке, не являющейся числом. Когда пользователь нажимает кнопку, а поля ввода пусты, метод getText().toString() возвращает пустую строку "". Попытка преобразовать её в число вызывает NumberFormatException. Это исключение не перехватывается, и приложение падает с сообщением "Unfortunately stopped".

Чтобы убедиться в этом, посмотрите Logcat (вкладка в Android Studio). Фильтр по слову "error" покажет стек вызовов с указанием строки, где произошла ошибка. Например:

java.lang.NumberFormatException: For input string: ""
    at java.lang.Integer.parseInt(Integer.java:627)
    at com.example.myapp.MainActivity$1.onClick(MainActivity.java:25)

Решение: корректная обработка ввода

Нужно проверить, что поля не пусты, и перехватить возможное исключение. Вот исправленный код:

public class MainActivity extends AppCompatActivity {
    EditText num1, num2;
    Button addBtn;
    TextView result;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        num1 = findViewById(R.id.num1);
        num2 = findViewById(R.id.num2);
        addBtn = findViewById(R.id.addBtn);
        result = findViewById(R.id.result);

        addBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                String text1 = num1.getText().toString().trim();
                String text2 = num2.getText().toString().trim();

                // Проверка на пустоту
                if (text1.isEmpty() || text2.isEmpty()) {
                    Toast.makeText(MainActivity.this, 
                        "Пожалуйста, заполните оба поля!", Toast.LENGTH_SHORT).show();
                    return;
                }

                try {
                    int a = Integer.parseInt(text1);
                    int b = Integer.parseInt(text2);
                    result.setText("Сумма: " + (a + b));
                } catch (NumberFormatException e) {
                    Toast.makeText(MainActivity.this, 
                        "Введите корректные числа!", Toast.LENGTH_SHORT).show();
                    // Логируем ошибку для отладки
                    e.printStackTrace();
                }
            }
        });
    }
}

Дополнительные советы для начинающих

  • Всегда используйте try-catch при парсинге данных от пользователя. Ввод из UI — ненадёжный источник.
  • Trim() удаляет лишние пробелы, которые могут вызвать ошибку.
  • Не игнорируйте Logcat — это ваш главный инструмент поиска ошибок. Добавляйте свои сообщения через Log.d("TAG", "сообщение").
  • Для чисел с плавающей точкой используйте Double.parseDouble() или Float.parseFloat().

После этих исправлений приложение перестанет падать. Сообщение "Unfortunately stopped" теперь будет заменено понятными Toast-уведомлениями.

<<>>

Альтернативный подход: использование библиотеки Material Design

Если вы используете AndroidX, рекомендую заменить обычные EditText на TextInputEditText из библиотеки Material Design. Они встроенно проверяют ввод и показывают ошибки под полем. Пример:

// В build.gradle добавьте:
// implementation 'com.google.android.material:material:1.9.0'

// В layout используйте:
<com.google.android.material.textfield.TextInputLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content">
    <com.google.android.material.textfield.TextInputEditText
        android:id="@+id/num1"
        android:inputType="number"
        android:hint="Число 1"/>
</com.google.android.material.textfield.TextInputLayout>

В коде проверяйте через TextInputLayout:

TextInputLayout layout1 = findViewById(R.id.layout1);
String text1 = layout1.getEditText().getText().toString();
if (text1.isEmpty()) {
    layout1.setError("Поле обязательно");
    return;
} else {
    layout1.setError(null);
}

Этот подход делает UI более дружественным и автоматически показывает ошибки без Toast. Однако базовую обработку исключений (try-catch) всё равно нужно оставить на случай, если пользователь введёт буквы в поле с типом "number".