如何完成多个 SingleInstance Activity?
How to finish several SingleInstance Activities?
我有几个使用 launchMode SingleInstance 的活动。注销时我想完成所有活动并打开 launchScreen。
val intent = Intent(context, LauncherActivity::class.java)
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK)
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
(context as AppCompatActivity).finishAffinity()
context.startActivity(intent)
但是,如果我在启动器上按回activity,我将被转发到之前使用单实例模式启动的活动
我不知道您到底想做什么,但我觉得您可以以不同的方式重新设计您的应用程序以做得更好。
关于你的问题 - 我猜你可以检查 onStart 的活动,如果用户已经注销,如果他确实启动了一个单一的实例启动器 activity 并用 finish()
关闭这些活动.
I have several activities with launchMode SingleInstance. On log out i want to finish all activities and open launchScreen.
这是一种方法:
- 让所有活动扩展自定义
BaseActivity
。
- 点击注销按钮后,您可以使用LocalBroadcastManager发送本地广播(在您的应用程序内)。
- 在基础中 activity 您可以实现侦听器。您可以在侦听器内部调用
finish()
。
- 所以当用户点击注销按钮时,你向所有打开的活动发送本地广播。由于您的所有活动都扩展了公共
BaseActivity
,因此会调用侦听器并完成活动。
- 发送广播后,即可打开意向
LauncherActivity
.
见How to use LocalBroadcastManager?
更多。
P.S:您可以在onDestroy
中取消注册监听器。由于 activity 仍然存在,因此不会调用 onDestroy。如果它已经被摧毁,那么你就少了一个 activity 担心。
2018 年 11 月 1 日更新:
我已经测试了多种处理它的方法,例如事件传播、意图标志、计算 activity 个实例等。有一些奇怪的场景,例如顺序启动多个 singleInstance
活动。在这种情况下,中间活动根本不会启动(onCreate
方法不会被调用),在按下后退按钮后,它们就会启动。因此,之前的任何一种方法都行不通!由于这个问题有点奇怪,所以我尝试用有点奇怪的方式解决它。
我们在名为 LogoutHandler
的单例 object 中维护注销状态。它与 class LogoutAwareActivity
合作,除 LoginActivity
之外的所有活动都继承它,因为它不应受到注销机制的影响。当注销发生时,在 LogoutHandler
中设置一个标志,直到 LogoutAwareActivity
的最后一个 child 完成然后清除标志。
这是一个实现:
注销处理程序:
import java.util.*
object LogoutHandler {
private var isLogout = false
private var timerWatchDog: TimerWatchDog? = null
fun isLogout() = isLogout
fun onActivityDestroyed() {
if (isLogout) {
timerWatchDog?.refresh(Runnable {
isLogout = false
timerWatchDog = null
})
}
}
fun logout() {
isLogout = true
timerWatchDog = TimerWatchDog(500)
}
private class TimerWatchDog(private val delay: Long) : Runnable {
private var timer: Timer? = null
private var runnable: Runnable? = null
fun refresh(runnable: Runnable) {
this.runnable = runnable
timer?.cancel()
val timerTask = object : TimerTask() {
override fun run() {
Thread(this@TimerWatchDog).start()
}
}
timer = Timer()
timer?.schedule(timerTask, delay)
}
override fun run() {
runnable?.run()
}
}
}
LogoutAwareActivity:
import android.support.v7.app.AppCompatActivity
abstract class LogoutAwareActivity : AppCompatActivity() {
override fun onResume() {
super.onResume()
if (LogoutHandler.isLogout()) {
finish()
}
}
override fun onDestroy() {
super.onDestroy()
LoginHandler.onActivityDestroyed()
}
}
一个具体的Activity:
class ActivityA : LogoutAwareActivity() {
// ...
}
再具体Activity:
class ActivityB : LogoutAwareActivity() {
// ...
}
您的登出功能:
fun logout() {
val intent = Intent(context, LoginActivity::class.java)
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
LogoutHandler.logout()
context.startActivity(intent)
}
视觉结果:
MainActivity
、ActivityA
、ActivityB
和 ActivityC
都是单实例。
通过按后退按钮在活动之间移动:
前往 LoginActivity
然后按后退按钮:
在启动启动画面之前添加此行
ActivityCompat.finishAffinity(this)
根据我扩展应用程序的经验,class 是存储需要在所有活动之间共享的有限数据量的最简单、最有效的方法。
在您的情况下,您可以创建一个 class 保存您的登录数据并将其实例存储在您的自定义应用程序对象中,所有活动都可以访问它。他们可以在开始时检查登录可用性、订阅更改并在需要完成时得到通知。 Application 对象本身可以订阅更改并在需要时启动登录 activity。
我有几个使用 launchMode SingleInstance 的活动。注销时我想完成所有活动并打开 launchScreen。
val intent = Intent(context, LauncherActivity::class.java)
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK)
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
(context as AppCompatActivity).finishAffinity()
context.startActivity(intent)
但是,如果我在启动器上按回activity,我将被转发到之前使用单实例模式启动的活动
我不知道您到底想做什么,但我觉得您可以以不同的方式重新设计您的应用程序以做得更好。
关于你的问题 - 我猜你可以检查 onStart 的活动,如果用户已经注销,如果他确实启动了一个单一的实例启动器 activity 并用 finish()
关闭这些活动.
I have several activities with launchMode SingleInstance. On log out i want to finish all activities and open launchScreen.
这是一种方法:
- 让所有活动扩展自定义
BaseActivity
。 - 点击注销按钮后,您可以使用LocalBroadcastManager发送本地广播(在您的应用程序内)。
- 在基础中 activity 您可以实现侦听器。您可以在侦听器内部调用
finish()
。 - 所以当用户点击注销按钮时,你向所有打开的活动发送本地广播。由于您的所有活动都扩展了公共
BaseActivity
,因此会调用侦听器并完成活动。 - 发送广播后,即可打开意向
LauncherActivity
.
见How to use LocalBroadcastManager? 更多。
P.S:您可以在onDestroy
中取消注册监听器。由于 activity 仍然存在,因此不会调用 onDestroy。如果它已经被摧毁,那么你就少了一个 activity 担心。
2018 年 11 月 1 日更新:
我已经测试了多种处理它的方法,例如事件传播、意图标志、计算 activity 个实例等。有一些奇怪的场景,例如顺序启动多个 singleInstance
活动。在这种情况下,中间活动根本不会启动(onCreate
方法不会被调用),在按下后退按钮后,它们就会启动。因此,之前的任何一种方法都行不通!由于这个问题有点奇怪,所以我尝试用有点奇怪的方式解决它。
我们在名为 LogoutHandler
的单例 object 中维护注销状态。它与 class LogoutAwareActivity
合作,除 LoginActivity
之外的所有活动都继承它,因为它不应受到注销机制的影响。当注销发生时,在 LogoutHandler
中设置一个标志,直到 LogoutAwareActivity
的最后一个 child 完成然后清除标志。
这是一个实现:
注销处理程序:
import java.util.*
object LogoutHandler {
private var isLogout = false
private var timerWatchDog: TimerWatchDog? = null
fun isLogout() = isLogout
fun onActivityDestroyed() {
if (isLogout) {
timerWatchDog?.refresh(Runnable {
isLogout = false
timerWatchDog = null
})
}
}
fun logout() {
isLogout = true
timerWatchDog = TimerWatchDog(500)
}
private class TimerWatchDog(private val delay: Long) : Runnable {
private var timer: Timer? = null
private var runnable: Runnable? = null
fun refresh(runnable: Runnable) {
this.runnable = runnable
timer?.cancel()
val timerTask = object : TimerTask() {
override fun run() {
Thread(this@TimerWatchDog).start()
}
}
timer = Timer()
timer?.schedule(timerTask, delay)
}
override fun run() {
runnable?.run()
}
}
}
LogoutAwareActivity:
import android.support.v7.app.AppCompatActivity
abstract class LogoutAwareActivity : AppCompatActivity() {
override fun onResume() {
super.onResume()
if (LogoutHandler.isLogout()) {
finish()
}
}
override fun onDestroy() {
super.onDestroy()
LoginHandler.onActivityDestroyed()
}
}
一个具体的Activity:
class ActivityA : LogoutAwareActivity() {
// ...
}
再具体Activity:
class ActivityB : LogoutAwareActivity() {
// ...
}
您的登出功能:
fun logout() {
val intent = Intent(context, LoginActivity::class.java)
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
LogoutHandler.logout()
context.startActivity(intent)
}
视觉结果:
MainActivity
、ActivityA
、ActivityB
和 ActivityC
都是单实例。
通过按后退按钮在活动之间移动:
前往 LoginActivity
然后按后退按钮:
在启动启动画面之前添加此行
ActivityCompat.finishAffinity(this)
根据我扩展应用程序的经验,class 是存储需要在所有活动之间共享的有限数据量的最简单、最有效的方法。
在您的情况下,您可以创建一个 class 保存您的登录数据并将其实例存储在您的自定义应用程序对象中,所有活动都可以访问它。他们可以在开始时检查登录可用性、订阅更改并在需要完成时得到通知。 Application 对象本身可以订阅更改并在需要时启动登录 activity。