【问题标题】:What happen to the activity when i press back button?当我按下返回按钮时,活动会发生什么?
【发布时间】:2021-12-18 09:43:07
【问题描述】:

当我使用 Intent 进行活动 A(此处为 LoginActivity)并转到活动 B(此处为 MainActivity)并调用 finish() 函数时 意图功能后 示例:

 if (isloggedIn){
        val intent=Intent(this@LoginActivity,MainActivity::class.java)
        startActivity(intent)
        finish()
    }

当我按下返回按钮时,从 Activity B(此处为 MainActivity)会发生什么情况,Activity A 将再次被 onCreate() 调用,或者由于它不在堆栈中,我将被定向到我的手机主屏幕? 我目前遇到的错误让我对此感到困惑: 我做了上面提到的两个活动(A 和 B),并为此使用了 AutoLogin 功能。当用户第一次登录时它工作正常,但是当用户停止应用程序并清除内存并再次重新打开应用程序时,它成功进入 Activity B(MainActivity)而不询问用户的登录凭据,但是当我按下应用程序时崩溃为什么? 代码:

class LoginActivity : AppCompatActivity(){
lateinit var phone_num:EditText
lateinit var password_num:EditText
lateinit var button_login:Button
lateinit var txtForgotPassword:TextView
lateinit var RegisterYouself:TextView
val ValidMobileNumber="0123"
val ValidPassword= arrayOf("Iron","captain","hulk","avenger")
lateinit var SharedPreferences:SharedPreferences

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    SharedPreferences=getSharedPreferences(getString(R.string.Prefereces_file_name), Context.MODE_PRIVATE)

    val isloggedIn=SharedPreferences.getBoolean("isLoggedIn",false)

    if (isloggedIn){
        val intent=Intent(this@LoginActivity,MainActivity::class.java)
        startActivity(intent)
        finish()
    }
    else {
        setContentView(R.layout.activity_login)
    }




    title="Log In"

    phone_num=findViewById(R.id.phone_num)
    password_num=findViewById(R.id.password_num)
    button_login=findViewById(R.id.button_login)
    txtForgotPassword=findViewById(R.id.txtForgotPassword)
    RegisterYouself=findViewById(R.id.RegisterYouself)

    button_login.setOnClickListener{
        val mobilenumber=phone_num.text.toString()
        val password=password_num.text.toString()
        var nameOfAvenger="Avenger"
        val intent=Intent(this@LoginActivity,MainActivity::class.java)
        if (mobilenumber==ValidMobileNumber){
            if (password==ValidPassword[0]){

                nameOfAvenger="Iron Man"
                savePreferences(nameOfAvenger)

                startActivity(intent)
            }
            else if (password==ValidPassword[1]){

                nameOfAvenger="Captain America"
                savePreferences(nameOfAvenger)

                startActivity(intent)
            }
            else if(password==ValidPassword[2]){

                nameOfAvenger="Hulk"
                savePreferences(nameOfAvenger)

                startActivity(intent)
            }
            else if (password==ValidPassword[3]){

                nameOfAvenger="The Avenger"
                savePreferences(nameOfAvenger)

                startActivity(intent)
            }
            else {
                Toast.makeText(
                    this@LoginActivity, "Incorrect creditial", Toast.LENGTH_LONG
                ).show()
            }
        }
        else {
            Toast.makeText(
                this@LoginActivity, "Incorrect creditial", Toast.LENGTH_LONG
            ).show()
        }
    }
}
fun savePreferences(title:String){
    SharedPreferences.edit().putBoolean("isLoggedIn",true).apply()
    SharedPreferences.edit().putString("Title",title).apply()

}

}

错误:

Process: com.mustafa.activitylifecycle, PID: 26158
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.mustafa.activitylifecycle/com.mustafa.activitylifecycle.LoginActivity}: java.lang.NullPointerException: findViewById(R.id.phone_num) must not be null
    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2913)
    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3048)
    at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:78)
    at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:108)
    at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:68)
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1808)
    at android.os.Handler.dispatchMessage(Handler.java:106)
    at android.os.Looper.loop(Looper.java:193)
    at android.app.ActivityThread.main(ActivityThread.java:6669)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)
 Caused by: java.lang.NullPointerException: findViewById(R.id.phone_num) must not be null
    at com.mustafa.activitylifecycle.LoginActivity.onCreate(LoginActivity.kt:43)
    at android.app.Activity.performCreate(Activity.java:7136)
    at android.app.Activity.performCreate(Activity.java:7127)
    at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1271)
    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2893)

【问题讨论】:

  • 你可以简单地运行这段代码,看看会发生什么!!!您在执行此代码时是否遇到任何意外行为?
  • 是的,当我按下后退按钮时,我的应用程序崩溃了
  • 错误是什么?编辑您的问题以包含堆栈跟踪
  • 请检查我是否已编辑问题
  • this 对您有帮助吗?

标签: android kotlin android-activity


【解决方案1】:

您的问题:

您编写的代码仅在用户未登录时调用setContentView。因此,当用户已登录时,没有可查找的视图。

if (isloggedIn){
    val intent=Intent(this@LoginActivity,MainActivity::class.java)
    startActivity(intent)
    finish() // JUST BECAUSE YOU CALL FINISH DOES NOT MEAN THE METHOD STOPS EXECUTING
}
else {
    // CONTENT ONLY BEING SET IF NOT LOGGED IN
    setContentView(R.layout.activity_login)
}

title="Log In"

// IF NOT LOGGED IN, THERE IS NO "phone_num" TO FIND!!!! CRASH! BOOM!
phone_num=findViewById(R.id.phone_num)
password_num=findViewById(R.id.password_num)

解决方案

要么总是调用setContentView,因此无论您是否登录,视图都可用:

if (isloggedIn){
    val intent=Intent(this@LoginActivity,MainActivity::class.java)
    startActivity(intent)
    finish()
}

// REMOVE THE "else" - ALWAYS SET VIEWS SO THEY'RE VALID
setContentView(R.layout.activity_login)

title="Log In"

phone_num=findViewById(R.id.phone_num)
password_num=findViewById(R.id.password_num)

或者......只是提前返回:

if (isloggedIn){
    val intent=Intent(this@LoginActivity,MainActivity::class.java)
    startActivity(intent)
    finish()
    return // EARLY RETURN TO PREVENT THE REST OF THE IRRELEVANT CODE FROM RUNNING
}
else {
    setContentView(R.layout.activity_login)
}

title="Log In"

phone_num=findViewById(R.id.phone_num)
password_num=findViewById(R.id.password_num)

OR ... 将您的视图设置逻辑提取到作为 else 块一部分的函数中:

fun onCreate(...) {
    if (isloggedIn) {
        val intent=Intent(this@LoginActivity,MainActivity::class.java)
        startActivity(intent)
        finish()
    }
    else {
        initializeActivity()
    }
}

fun initializeActivity() {
    setContentView(R.layout.activity_login)

    title="Log In"

    phone_num=findViewById(R.id.phone_num)
    password_num=findViewById(R.id.password_num)
    // ETC
}

【讨论】:

  • finish 函数下面的代码也运行吗?
  • finish 函数 call 之后的代码 将运行,是的。调用finish 不仅仅会突然结束您所在方法的执行。
  • 但是它破坏了activity那么它有什么用呢?
  • 指示Activity销毁。这与计算机执行它被指示执行的代码行是不同的并且是分开的。调用 finish 告诉 Activity 关闭 - 它不会告诉 JVM 停止执行代码,它会盲目地这样做。
  • 一旦我们调用finish()并移动到另一个活动然后(就像我所做的那样)然后按回它会再次回到loginActivity,如果是那么为什么一旦我们调用finish()那么它应该从 Activity 堆栈中删除,我应该登陆我的移动主页,但它没有发生,为什么?
猜你喜欢
  • 1970-01-01
  • 2017-11-01
  • 2016-12-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-03-17
  • 1970-01-01
相关资源
最近更新 更多