点击退出登录按钮后强制登出功能实现方案

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

问题:

Android开发,用Kotlin语言。在SixthActivity中,要实现点击logout按钮后退出登录的功能。SixthActivity 代码如下: package com.example.activitytest

import android.content.Intent import android.os.Bundle import android.os.Handler import android.os.Looper import android.widget.Button import androidx.activity.enableEdgeToEdge import androidx.appcompat.app.AppCompatActivity import androidx.core.view.ViewCompat import androidx.core.view.WindowInsetsCompat import android.widget.TextView import androidx.activity.result.ActivityResultLauncher import java.text.SimpleDateFormat import java.util.*

class SixthActivity : AppCompatActivity() { private lateinit var startForResult: ActivityResultLauncher<Intent> private lateinit var timeTextView: TextView private val handler = Handler(Looper.getMainLooper()) private val updateTimeRunnable = object : Runnable { override fun run() { updateTime() handler.postDelayed(this, 5000) // 每5秒更新一次 } }

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

    timeTextView = findViewById(R.id.timeTextView)

    ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.timeTextView)) { v, insets ->
        val systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars())
        v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom)
        insets
    }

    // 开始定时更新时间
    handler.post(updateTimeRunnable)

    //点击logoutBtn,退出登录
    val logoutBtn: Button = findViewById(R.id.logoutBtn)
    logoutBtn.setOnClickListener {
        val intent = Intent("com.example.activitytest.FORCE_LOGOUT")
        sendBroadcast(intent)
    }
}

override fun onDestroy() {
    super.onDestroy()
    // 停止定时更新
    handler.removeCallbacks(updateTimeRunnable)
}

private fun updateTime() {
    val currentTime = Calendar.getInstance().time
    val dateFormat = SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.getDefault())
    val formattedTime = "当前时间:${dateFormat.format(currentTime)}"
    timeTextView.text = formattedTime
}

}

BaseActivityClass 如下: package com.example.activitytest

import android.os.Bundle import android.util.Log import androidx.appcompat.app.AppCompatActivity import android.app.AlertDialog import android.content.BroadcastReceiver import android.content.Context import android.content.Intent import android.content.IntentFilter

open class BaseActivityClass : AppCompatActivity() {

private lateinit var receiver: ForceLogoutReceiver

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    //打印当前实例类名
    Log.d("BaseActivity", javaClass.simpleName)
    ActivityCollector.addActivity(this)
}


override fun onResume() {
    super.onResume()
    val intentFilter = IntentFilter()
    intentFilter.addAction("com.example.activitytest.FORCE_LOGOUT")
    receiver = ForceLogoutReceiver()
    registerReceiver(receiver, intentFilter)
}

override fun onPause() {
    super.onPause()
    unregisterReceiver(receiver)
}

override fun onDestroy() {
    super.onDestroy()
    ActivityCollector.removeActivity(this)
}

inner class ForceLogoutReceiver : BroadcastReceiver() {

    override fun onReceive(context: Context, intent: Intent) {
        AlertDialog.Builder(context).apply {
            setTitle("Warning")
            setMessage("You are forced to be logout. Please try to login again.")
            setCancelable(false)  //不可取消
            setPositiveButton("确定") { _, _ ->
                ActivityCollector.finishAll() // 销毁所有Activity
                val i = Intent(context, LoginActivity::class.java)
                context.startActivity(i) // 重新启动LoginActivity
            }
            show()
        }
    }
}

}

sixth_layout.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/sixLayout" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".SixthActivity">

<TextView
    android:id="@+id/timeTextView"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_marginTop="16dp"
    android:textSize="18sp"
    android:textColor="@android:color/black"
    app:layout_constraintTop_toTopOf="parent"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintHorizontal_bias="0.5"
    app:layout_constraintVertical_bias="0.0"/>

<Button
    android:id="@+id/logoutBtn"
    android:layout_width="200dp"
    android:layout_height="60dp"
    android:text="退出登录"
    app:layout_constraintTop_toBottomOf="@+id/timeTextView"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintVertical_bias="0.1"
    android:layout_marginTop="24dp"/>

</androidx.constraintlayout.widget.ConstraintLayout>

但是运行后,点击logout按钮后,并没有退出登录,界面没有任何反应。 请分析原因,并解决问题。

答案:

从你提供的代码来看,问题可能出在以下几个方面:

  1. SixthActivity 没有继承 BaseActivityClass:你在 BaseActivityClass 中实现了接收广播并处理强制登出的逻辑,但 SixthActivity 并没有继承 BaseActivityClass,因此它不会接收到广播。

  2. BroadcastReceiver 注册和注销:确保 BroadcastReceiveronResume 中注册,在 onPause 中注销。

  3. ActivityCollector:确保 ActivityCollector 正确实现了 addActivityfinishAll 方法。

解决方案

  1. 让 SixthActivity 继承 BaseActivityClass
class SixthActivity : BaseActivityClass() {
    // 其余代码保持不变
}
  1. 确保 ActivityCollector 正确实现
object ActivityCollector {
    private val activities = ArrayList<AppCompatActivity>()

    fun addActivity(activity: AppCompatActivity) {
        activities.add(activity)
    }

    fun removeActivity(activity: AppCompatActivity) {
        activities.remove(activity)
    }

    fun finishAll() {
        for (activity in activities) {
            if (!activity.isFinishing) {
                activity.finish()
            }
        }
        activities.clear()
    }
}
  1. 确保 LoginActivity 存在并正确实现
class LoginActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_login)
        // 其他登录逻辑
    }
}

完整代码

SixthActivity.kt

package com.example.activitytest

import android.content.Intent
import android.os.Bundle
import android.os.Handler
import android.os.Looper
import android.widget.Button
import androidx.activity.enableEdgeToEdge
import androidx.core.view.ViewCompat
import androidx.core.view.WindowInsetsCompat
import android.widget.TextView
import androidx.activity.result.ActivityResultLauncher
import java.text.SimpleDateFormat
import java.util.*

class SixthActivity : BaseActivityClass() { // 继承 BaseActivityClass
    private lateinit var startForResult: ActivityResultLauncher<Intent>
    private lateinit var timeTextView: TextView
    private val handler = Handler(Looper.getMainLooper())
    private val updateTimeRunnable = object : Runnable {
        override fun run() {
            updateTime()
            handler.postDelayed(this, 5000) // 每5秒更新一次
        }
    }

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

        timeTextView = findViewById(R.id.timeTextView)

        ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.timeTextView)) { v, insets ->
            val systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars())
            v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom)
            insets
        }

        // 开始定时更新时间
        handler.post(updateTimeRunnable)

        //点击logoutBtn,退出登录
        val logoutBtn: Button = findViewById(R.id.logoutBtn)
        logoutBtn.setOnClickListener {
            val intent = Intent("com.example.activitytest.FORCE_LOGOUT")
            sendBroadcast(intent)
        }
    }

    override fun onDestroy() {
        super.onDestroy()
        // 停止定时更新
        handler.removeCallbacks(updateTimeRunnable)
    }

    private fun updateTime() {
        val currentTime = Calendar.getInstance().time
        val dateFormat = SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.getDefault())
        val formattedTime = "当前时间:${dateFormat.format(currentTime)}"
        timeTextView.text = formattedTime
    }
}

BaseActivityClass.kt

package com.example.activitytest

import android.os.Bundle
import android.util.Log
import androidx.appcompat.app.AppCompatActivity
import android.app.AlertDialog
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.content.IntentFilter

open class BaseActivityClass : AppCompatActivity() {

    private lateinit var receiver: ForceLogoutReceiver

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        //打印当前实例类名
        Log.d("BaseActivity", javaClass.simpleName)
        ActivityCollector.addActivity(this)
    }

    override fun onResume() {
        super.onResume()
        val intentFilter = IntentFilter()
        intentFilter.addAction("com.example.activitytest.FORCE_LOGOUT")
        receiver = ForceLogoutReceiver()
        registerReceiver(receiver, intentFilter)
    }

    override fun onPause() {
        super.onPause()
        unregisterReceiver(receiver)
    }

    override fun onDestroy() {
        super.onDestroy()
        ActivityCollector.removeActivity(this)
    }

    inner class ForceLogoutReceiver : BroadcastReceiver() {

        override fun onReceive(context: Context, intent: Intent) {
            AlertDialog.Builder(context).apply {
                setTitle("Warning")
                setMessage("You are forced to be logout. Please try to login again.")
                setCancelable(false)  //不可取消
                setPositiveButton("确定") { _, _ ->
                    ActivityCollector.finishAll() // 销毁所有Activity
                    val i = Intent(context, LoginActivity::class.java)
                    context.startActivity(i) // 重新启动LoginActivity
                }
                show()
            }
        }
    }
}

ActivityCollector.kt

package com.example.activitytest

import androidx.appcompat.app.AppCompatActivity

object ActivityCollector {
    private val activities = ArrayList<AppCompatActivity>()

    fun addActivity(activity: AppCompatActivity) {
        activities.add(activity)
    }

    fun removeActivity(activity: AppCompatActivity) {
        activities.remove(activity)
    }

    fun finishAll() {
        for (activity in activities) {
            if (!activity.isFinishing) {
                activity.finish()
            }
        }
        activities.clear()
    }
}

LoginActivity.kt

package com.example.activitytest

import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity

class LoginActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_login)
        // 其他登录逻辑
    }
}

这样修改后,点击 logoutBtn 按钮时,SixthActivity 会发送广播,BaseActivityClass 中的 BroadcastReceiver 会接收到广播并处理强制登出的逻辑。