我的应用程序崩溃并显示“CurrencyConverter 不断崩溃”。老实说,我看不出哪里有错误。
package com.example.currencycalculator
import android.app.Activity
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.text.Editable
import android.text.TextWatcher
import android.view.View
import android.view.ViewGroup
import android.widget.*
import android.widget.Spinner
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
var currencyPicker: Spinner = findViewById(R.id.spinner)
var userInput : EditText = findViewById(R.id.userInput)
var toConvert : Currencies = Currencies(userInput)
var convertedText : TextView = findViewById(R.id.endText)
ArrayAdapter.createFromResource(
this, R.array.currencyArray, android.R.layout.simple_spinner_item
).also { adapter ->
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item)
currencyPicker.adapter = adapter
}
currencyPicker.onItemSelectedListener = SpinnerActivity()
userInput.addTextChangedListener(object : TextWatcher {
override fun afterTextChanged(p0: Editable?) {
}
override fun beforeTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {
}
override fun onTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {
currencyPicker.setSelection(0)
}
})
}
inner class SpinnerActivity : Activity(), AdapterView.OnItemSelectedListener {
val userInput : EditText = findViewById(R.id.userInput)
var toConvert : Currencies = Currencies(userInput)
override fun onNothingSelected(p0: AdapterView<*>?) {
}
override fun onItemSelected(p0: AdapterView<*>?, p1: View?, p2: Int, p3: Long) {
if (p2 == 0)
{
toConvert.getPesos(userInput)
}
if (p2 == 1)
{
toConvert.getCan(userInput)
}
if (p2 == 2)
{
toConvert.getPesos(userInput)
}
}
}
}
activity_main.xml <
?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:id="@+id/layone"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<TextView
android:id="@+id/prompt"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Please choose the country to convert to:"
android:textSize="18sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.414" />
<Spinner
android:id="@+id/spinner"
android:layout_width="match_parent"
android:layout_height="wrap_content"
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="@+id/prompt"
app:layout_constraintVertical_bias="0.093" />
<EditText
android:id="@+id/userInput"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:ems="10"
android:inputType="numberDecimal"
app:layout_constraintBottom_toTopOf="@+id/prompt"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/endText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="30sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/spinner"
tools:text="Conversion:" />
</androidx.constraintlayout.widget.ConstraintLayout>
Currencies.kt
package com.example.currencycalculator
import android.widget.EditText
class Currencies(userInput: EditText) {
fun getPesos(totalAmt:EditText): Double {
var total: Double = totalAmt.text.toString().toDouble()
//if (!totalAmt.text.toString().isEmpty()) {
val converted : Double = total * 20.765275
return converted
//}
//else
// return null!!.toDouble()
}
fun getCan(totalAmt:EditText) : Double {
var total: Double = totalAmt.text.toString().toDouble()
//if (!totalAmt.text.toString().isEmpty()) {
val converted : Double = total * 1.257629
return converted
//}
//else
//return null!!.toDouble()
}
fun getEuros(totalAmt:EditText) : Double {
var total: Double = totalAmt.text.toString().toDouble()
//if (!totalAmt.text.toString().isEmpty()) {
val converted : Double = total * 0.836502
return converted
//}
//else
//eturn null!!.toDouble()
}
}
这是 Logcat:
03/11 13:40:34: Launching 'app' on No Devices.
App restart successful without requiring a re-install.
$ adb shell am start -n "com.example.currencycalculator/com.example.currencycalculator.MainActivity" -a android.intent.action.MAIN -c android.intent.category.LAUNCHER
Connected to process 3515 on device 'emulator-5554'.
Capturing and displaying logcat messages from application. This behavior can be disabled in the "Logcat output" section of the "Debugger" settings page.
W/RenderThread: type=1400 audit(0.0:252): avc: denied { write } for name="property_service" dev="tmpfs" ino=6766 scontext=u:r:untrusted_app:s0:c139,c256,c512,c768 tcontext=u:object_r:property_socket:s0 tclass=sock_file permissive=0
D/libEGL: Emulator has host GPU support, qemu.gles is set to 1.
W/libc: Unable to set property "qemu.gles" to "1": connection failed; errno=13 (Permission denied)
D/libEGL: loaded /vendor/lib/egl/libEGL_emulation.so
D/libEGL: loaded /vendor/lib/egl/libGLESv1_CM_emulation.so
D/libEGL: loaded /vendor/lib/egl/libGLESv2_emulation.so
W/rencycalculato: Accessing hidden method Landroid/view/View;->computeFitSystemWindows(Landroid/graphics/Rect;Landroid/graphics/Rect;)Z (greylist, reflection, allowed)
W/rencycalculato: Accessing hidden method Landroid/view/ViewGroup;->makeOptionalFitsSystemWindows()V (greylist, reflection, allowed)
D/AndroidRuntime: Shutting down VM
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.currencycalculator, PID: 3515
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.currencycalculator/com.example.currencycalculator.MainActivity}: java.lang.NullPointerException: Attempt to invoke virtual method 'android.view.View android.view.Window.findViewById(int)' on a null object reference
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3270)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3409)
at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:83)
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2016)
at android.os.Handler.dispatchMessage(Handler.java:107)
at android.os.Looper.loop(Looper.java:214)
at android.app.ActivityThread.main(ActivityThread.java:7356)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:930)
Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'android.view.View android.view.Window.findViewById(int)' on a null object reference
at android.app.Activity.findViewById(Activity.java:3209)
at com.example.currencycalculator.MainActivity$SpinnerActivity.<init>(MainActivity.kt:43)
at com.example.currencycalculator.MainActivity.onCreate(MainActivity.kt:27)
at android.app.Activity.performCreate(Activity.java:7802)
at android.app.Activity.performCreate(Activity.java:7791)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1299)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3245)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3409)
at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:83)
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2016)
at android.os.Handler.dispatchMessage(Handler.java:107)
at android.os.Looper.loop(Looper.java:214)
at android.app.ActivityThread.main(ActivityThread.java:7356)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:930)
这是一个货币转换器应用程序,我使用 Spinner 来选择用户想要转换成的货币。货币类只包含计算每种货币的函数。
在 MainActivity 中,我尝试使用 TextWatcher 来更新转换后的值,并通过 TextView 表示它(因此没有使用按钮)。 EditText 接受用户输入,该值由 Currencies 类使用。
答案 0 :(得分:0)
你的内部类毫无理由地是 Activity 的子类。当您从此类内部调用 findViewById
时,它正在调用内部类的 findViewById
,而不是 MainActivity。
由于您没有将内部类用作适当的 Activity,它没有设置任何视图,因此 findViewById
将失败。
将您的内部类更改为匿名对象(并删除其冗余属性),就像您用于文本观察器一样。
currencyPicker.onItemSelectedListener = object: AdapterView.OnItemSelectedListener {
override fun onNothingSelected(parent: AdapterView<*>) {
}
override fun onItemSelected(parent: AdapterView<*>, view: View, position: Int, id: Long) {
if (position == 0)
{
toConvert.getPesos(userInput)
}
if (position == 1)
{
toConvert.getCan(userInput)
}
if (position == 2)
{
toConvert.getPesos(userInput)
}
}
}
我还建议使用 when
语句以提高可读性:
override fun onItemSelected(parent: AdapterView<*>, view: View, position: Int, id: Long) {
when(position) {
0, 2 -> toConvert.getPesos(userInput)
1 -> toConvert.getCan(userInput)
}
}