在EditText框中输入数字时出现Android运行时错误



我正在创建一个简单的卡路里到千焦耳的计算器,当用户在两个EditText框中输入一个数字时,它应该提供转换(类似于您在这里看到的转换器类型)。我使用chat.openai.com作为MainActivity.kt中的大部分代码。

然而,每当我输入一个数字,应用程序将冻结并立即崩溃,由于运行时错误。有人能帮助排除为什么文本监视程序可能导致这些崩溃吗?

Logcat Error Log:

at com.example.energyconverter.MainActivity$onCreate$textWatcher$1.onTextChanged(MainActivity.kt:41)
at android.widget.TextView.sendOnTextChanged(TextView.java:10789)
at android.widget.TextView.setText(TextView.java:6401)
at android.widget.TextView.setText(TextView.java:6227)
at android.widget.EditText.setText(EditText.java:121)
at android.widget.TextView.setText(TextView.java:6179)
at com.example.energyconverter.MainActivity$onCreate$textWatcher$1.onTextChanged(MainActivity.kt:47)
at android.widget.TextView.sendOnTextChanged(TextView.java:10789)
at android.widget.TextView.setText(TextView.java:6401)
at android.widget.TextView.setText(TextView.java:6227)
at android.widget.EditText.setText(EditText.java:121)
at android.widget.TextView.setText(TextView.java:6179)
at com.example.energyconverter.MainActivity$onCreate$textWatcher$1.onTextChanged(MainActivity.kt:41)
at android.widget.TextView.sendOnTextChanged(TextView.java:10789)
at android.widget.TextView.handleTextChanged(TextView.java:10904)
at android.widget.TextView$ChangeWatcher.onTextChanged(TextView.java:13807)
at android.text.SpannableStringBuilder.sendTextChanged(SpannableStringBuilder.java:1268)
at android.text.SpannableStringBuilder.replace(SpannableStringBuilder.java:577)
at androidx.emoji2.text.SpannableBuilder.replace(SpannableBuilder.java:315)
at android.text.SpannableStringBuilder.replace(SpannableStringBuilder.java:508)
at androidx.emoji2.text.SpannableBuilder.replace(SpannableBuilder.java:305)
at androidx.emoji2.text.SpannableBuilder.replace(SpannableBuilder.java:49)
at android.text.method.NumberKeyListener.onKeyDown(NumberKeyListener.java:129)
at android.widget.TextView.doKeyDown(TextView.java:8557)
at android.widget.TextView.onKeyDown(TextView.java:8331)
at android.view.KeyEvent.dispatch(KeyEvent.java:2854)
at android.view.View.dispatchKeyEvent(View.java:14478)
at android.view.ViewGroup.dispatchKeyEvent(ViewGroup.java:1964)
at android.view.ViewGroup.dispatchKeyEvent(ViewGroup.java:1964)
at android.view.ViewGroup.dispatchKeyEvent(ViewGroup.java:1964)
at android.view.ViewGroup.dispatchKeyEvent(ViewGroup.java:1964)
at android.view.ViewGroup.dispatchKeyEvent(ViewGroup.java:1964)
at android.view.ViewGroup.dispatchKeyEvent(ViewGroup.java:1964)
09:42:09.998  E     at com.android.internal.policy.DecorView.superDispatchKeyEvent(DecorView.java:490)
at com.android.internal.policy.PhoneWindow.superDispatchKeyEvent(PhoneWindow.java:1880)
at android.app.Activity.dispatchKeyEvent(Activity.java:4156)
at androidx.core.app.ComponentActivity.superDispatchKeyEvent(ComponentActivity.java:124)
at androidx.core.view.KeyEventDispatcher.dispatchKeyEvent(KeyEventDispatcher.java:86)
at androidx.core.app.ComponentActivity.dispatchKeyEvent(ComponentActivity.java:142)
at androidx.appcompat.app.AppCompatActivity.dispatchKeyEvent(AppCompatActivity.java:601)
at androidx.appcompat.view.WindowCallbackWrapper.dispatchKeyEvent(WindowCallbackWrapper.java:60)
at androidx.appcompat.app.AppCompatDelegateImpl$AppCompatWindowCallback.dispatchKeyEvent(AppCompatDelegateImpl.java:3106)
at com.android.internal.policy.DecorView.dispatchKeyEvent(DecorView.java:404)
at android.view.ViewRootImpl$ViewPostImeInputStage.processKeyEvent(ViewRootImpl.java:6278)
at android.view.ViewRootImpl$ViewPostImeInputStage.onProcess(ViewRootImpl.java:6144)
at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:5626)
at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:5683)
at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:5649)
at android.view.ViewRootImpl$AsyncInputStage.forward(ViewRootImpl.java:5814)
at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:5657)
at android.view.ViewRootImpl$AsyncInputStage.apply(ViewRootImpl.java:5871)
at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:5630)
at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:5683)
at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:5649)
at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:5657)
at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:5630)
at android.view.ViewRootImpl.deliverInputEvent(ViewRootImpl.java:8562)
at android.view.ViewRootImpl.doProcessInputEvents(ViewRootImpl.java:8513)
at android.view.ViewRootImpl.enqueueInputEvent(ViewRootImpl.java:8482)
at android.view.ViewRootImpl$ViewRootHandler.handleMessageImpl(ViewRootImpl.java:5391)
at android.view.ViewRootImpl$ViewRootHandler.handleMessage(ViewRootImpl.java:5263)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loopOnce(Looper.java:201)
at android.os.Looper.loop(Looper.java:288)
at android.app.ActivityThread.main(ActivityThread.java:7839)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:548)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1003)

MainActivity.kt:

package com.example.energyconverter
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.text.Editable
import android.text.TextWatcher
import android.widget.EditText
class MainActivity : AppCompatActivity() {
// Define constants for the conversion factor between kilojoules and calories
private val KJ_TO_CAL = 4.184
private val CAL_TO_KJ = 1.0 / KJ_TO_CAL
// Define the EditText widgets for the kilojoules and calories
private lateinit var kilojoulesText: EditText
private lateinit var caloriesText: EditText
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
kilojoulesText = findViewById(R.id.kilojoules_text)
caloriesText = findViewById(R.id.calories_text)
// Set up a TextWatcher to update the conversion when the user types in either text box
val textWatcher = object : TextWatcher {
override fun afterTextChanged(s: Editable?) {
// Do nothing
}
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {
// Do nothing
}
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
// Convert the value in the other text box when the user types in either one
if (s == kilojoulesText.text) {
val kj = s.toString().toDoubleOrNull()
if (kj != null) {
val cal = kj * KJ_TO_CAL
caloriesText.setText(cal.toString())
}
} else if (s == caloriesText.text) {
val cal = s.toString().toDoubleOrNull()
if (cal != null) {
val kj = cal * CAL_TO_KJ
kilojoulesText.setText(kj.toString())
}
}
}
}
// Attach the TextWatcher to both EditText widgets
kilojoulesText.addTextChangedListener(textWatcher)
caloriesText.addTextChangedListener(textWatcher)
}
}

activity_main.xml(请允许我对这些EditText框进行对齐,因为我现在刚刚将它们扔到屏幕上)

<?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">
<EditText
android:id="@+id/calories_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="100dp"
android:layout_marginTop="154dp"
android:layout_marginEnd="101dp"
android:ems="10"
android:hint="@string/text_calories_hint"
android:importantForAutofill="no"
android:inputType="number"
android:textColorHint="#757575"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="parent"
app:layout_constraintVertical_bias="1.0"
tools:ignore="TouchTargetSizeCheck,TouchTargetSizeCheck" />
<EditText
android:id="@+id/kilojoules_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="99dp"
android:layout_marginTop="180dp"
android:layout_marginEnd="102dp"
android:layout_marginBottom="484dp"
android:ems="10"
android:hint="@string/text_kilojoules_hint"
android:importantForAutofill="no"
android:inputType="number"
android:minHeight="48dp"
android:textColorHint="#757575"
app:layout_constraintBottom_toTopOf="@+id/calories_text"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="1.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>

由于我是Kotlin和Android Studio的新手,我所能做的最多的就是利用LOGCAT来了解问题的根源。LOGCAT指向下面两行:

caloriesText.setText(cal.toString())
kilojoulesText.setText(kj.toString())
class SomeActivity : AppCompatActivity() {
// Define constants for the conversion factor between kilojoules and calories
private val KJ_TO_CAL = 4.184
private val CAL_TO_KJ = 1.0 / KJ_TO_CAL
// Define the EditText widgets for the kilojoules and calories
private lateinit var kilojoulesText: EditText
private lateinit var caloriesText: EditText
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_some)
kilojoulesText = findViewById(R.id.kilojoules_text)
caloriesText = findViewById(R.id.calories_text)
// Set up a TextWatcher to update the conversion when the user types in either text box
val textWatcher = object : TextWatcher {
override fun afterTextChanged(s: Editable?) {
// Do nothing
}
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {
// Do nothing
}
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
if (caloriesText.isFocused) {
if (s == caloriesText.text) {
val kj = s.toString().toDoubleOrNull()
if (kj != null) {
val cal = kj * KJ_TO_CAL
kilojoulesText.setText(cal.toString())
}
}
}
if (kilojoulesText.isFocused) {
if (s == kilojoulesText.text) {
val cal = s.toString().toDoubleOrNull()
if (cal != null) {
val kj = cal * CAL_TO_KJ
caloriesText.setText(kj.toString())
}
}
}
}
}
// Attach the TextWatcher to both EditText widgets
kilojoulesText.addTextChangedListener(textWatcher)
caloriesText.addTextChangedListener(textWatcher)
}
}

嗨@JTek,你能试一下这个代码,让我知道它是否按预期工作。我在这里做了一个小改动。我添加了一个检查,通过检查EditText的焦点状态来查看哪个EditText用户正在对其进行更改。这将帮助我们防止回调的无限循环。

简单来说,如果用户试图计算KJ,那么我们应该只听卡路里EditText的变化,反之亦然。

相关内容

  • 没有找到相关文章

最新更新