修复Android Kotlin登录界面启动异常问题

使用 GPT-4o 回答,作者 GPT4oMini.app

问题:

Android开发,用Kotlin语言。以下是LoginActivity : package com.example.activitytest

import android.content.Intent import android.os.Bundle import android.widget.Button import android.widget.EditText import android.widget.TextView import android.widget.Toast import androidx.activity.result.ActivityResultLauncher

class LoginActivity : BaseActivityClass() {

private lateinit var startForResult: ActivityResultLauncher<Intent>

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.login_layout)

    //登录
    val login: Button = findViewById(R.id.login)
    val accountEdit: EditText = findViewById(R.id.accountEdit)
    val passwordEdit:EditText = findViewById(R.id.passwordEdit)

    login.setOnClickListener {
        val account = accountEdit.text.toString()
        val password = passwordEdit.text.toString()
        // 如果账号是admin且密码是123456,就认为登录成功
        if (account == "admin" && password == "123456") {
            val intent = Intent(this, SixthActivity::class.java)
            startForResult.launch(intent)
            finish()
        } else {
            Toast.makeText(this, "用户名或密码错误!请重新输入。",
                Toast.LENGTH_SHORT).show()
        }
    }
}

}

login_layout.xml如下:

<?xml version="1.0" encoding="utf-8"?>

<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:id="@+id/loginLayout" xmlns:app="http://schemas.android.com/apk/res-auto">

<TextView
    android:id="@+id/accountLabel"
    android:layout_width="0dp"
    android:layout_height="wrap_content"
    android:textSize="18sp"
    android:text="Account:"
    app:layout_constraintEnd_toStartOf="@+id/accountEdit"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toTopOf="parent"
    app:layout_constraintVertical_bias="0.1"
    android:layout_marginEnd="8dp"
    android:layout_marginTop="16dp"/>

<EditText
    android:id="@+id/accountEdit"
    android:layout_width="0dp"
    android:layout_height="48dp"
    android:layout_marginTop="16dp"
    android:hint="Enter your account"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintStart_toEndOf="@+id/accountLabel"
    app:layout_constraintTop_toTopOf="@+id/accountLabel"
    app:layout_constraintHorizontal_bias="0"
    android:layout_marginStart="8dp"/>

<TextView
    android:id="@+id/passwordLabel"
    android:layout_width="0dp"
    android:layout_height="wrap_content"
    android:textSize="18sp"
    android:text="Password:"
    app:layout_constraintEnd_toStartOf="@+id/passwordEdit"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toBottomOf="@+id/accountEdit"
    app:layout_constraintVertical_bias="0.1"
    android:layout_marginEnd="8dp"
    android:layout_marginTop="16dp"/>

<EditText
    android:id="@+id/passwordEdit"
    android:layout_width="0dp"
    android:layout_height="48dp"
    android:layout_marginTop="16dp"
    android:inputType="textPassword"
    android:hint="Enter your password"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintStart_toEndOf="@+id/passwordLabel"
    app:layout_constraintTop_toTopOf="@+id/passwordLabel"
    app:layout_constraintHorizontal_bias="0"
    android:layout_marginStart="8dp"/>

<Button
    android:id="@+id/login"
    android:layout_width="200dp"
    android:layout_height="60dp"
    android:text="Login"
    app:layout_constraintTop_toBottomOf="@+id/passwordEdit"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintVertical_bias="0.1"
    android:layout_marginTop="24dp"/>

</androidx.constraintlayout.widget.ConstraintLayout>

app运行时,点击login按钮,并没有跳转到SixthActivity,而是跳转到了MainActivity。并且后台报错如下: FATAL EXCEPTION: main Process: com.example.activitytest, PID: 8763 kotlin.UninitializedPropertyAccessException: lateinit property startForResult has not been initialized at com.example.activitytest.LoginActivity.onCreate$lambda$0(LoginActivity.kt:30) at com.example.activitytest.LoginActivity.$r8$lambda$urr-jB8pw2bKwGz66-jcJ9K6uDM(Unknown Source:0) at com.example.activitytest.LoginActivity$$ExternalSyntheticLambda0.onClick(D8$$SyntheticClass:0) at android.view.View.performClick(View.java:7322) at com.google.android.material.button.MaterialButton.performClick(MaterialButton.java:1213) at android.view.View.performClickInternal(View.java:7296) at android.view.View.access$3600(View.java:839) at android.view.View$PerformClick.run(View.java:28319) at android.os.Handler.handleCallback(Handler.java:908) at android.os.Handler.dispatchMessage(Handler.java:103) at android.os.Looper.loop(Looper.java:219) at android.app.ActivityThread.main(ActivityThread.java:8679) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:513) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1109)

请分析原因,并修复问题。

答案:

从错误日志中可以看出,startForResult 属性在使用前没有被初始化,导致了 kotlin.UninitializedPropertyAccessException 异常。这个异常发生在 LoginActivityonCreate 方法中,当点击登录按钮时触发。

为了修复这个问题,你需要在 onCreate 方法中初始化 startForResult。在 Android 中,使用 ActivityResultLauncher 需要通过 registerForActivityResult 方法进行初始化。以下是修复后的代码:

package com.example.activitytest

import android.content.Intent
import android.os.Bundle
import android.widget.Button
import android.widget.EditText
import android.widget.TextView
import android.widget.Toast
import androidx.activity.result.ActivityResultLauncher
import androidx.activity.result.contract.ActivityResultContracts
import androidx.appcompat.app.AppCompatActivity

class LoginActivity : AppCompatActivity() {

    private lateinit var startForResult: ActivityResultLauncher<Intent>

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.login_layout)

        // 初始化 startForResult
        startForResult = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
            // 处理返回结果
            if (result.resultCode == RESULT_OK) {
                // 处理成功的结果
            }
        }

        // 登录
        val login: Button = findViewById(R.id.login)
        val accountEdit: EditText = findViewById(R.id.accountEdit)
        val passwordEdit: EditText = findViewById(R.id.passwordEdit)

        login.setOnClickListener {
            val account = accountEdit.text.toString()
            val password = passwordEdit.text.toString()
            // 如果账号是admin且密码是123456,就认为登录成功
            if (account == "admin" && password == "123456") {
                val intent = Intent(this, SixthActivity::class.java)
                startForResult.launch(intent)
                finish()
            } else {
                Toast.makeText(this, "用户名或密码错误!请重新输入。", Toast.LENGTH_SHORT).show()
            }
        }
    }
}

在上面的代码中,我们在 onCreate 方法中使用 registerForActivityResult 方法初始化了 startForResult。这样,当点击登录按钮时,startForResult 已经被正确初始化,可以正常启动 SixthActivity

此外,确保 SixthActivityAndroidManifest.xml 中正确声明:

<activity android:name=".SixthActivity" />

这样可以确保 SixthActivity 能够被正确启动。