【Util】ActivityManage Activity 管理器 範例
Android ActivityManage,是Android在應用中使用的管理活動的繼承框架。
它能讓Android開發者建立可以執行靈活活動之間切換,管理進入及離開活動,活動間切換時候的暫停及繼續和加載活動及資源等更為完善與靈活的應用。
本文將說明Android ActivityManage的重要性及功能,並且介紹如何實現它以及它對Android應用開發的影響。
文章目錄
- ActivityManage
- ActivityManage Application
- ActivityManage Activity
- ActivityManage pop
- ActivityManage popUntil
- ActivityManage onExit
1.ActivityManage
ActivityManage.kt
object ActivityManage {
private val STACK = ActivityStack()
private lateinit var topActivity: WeakReference<Activity>
private lateinit var operations: ExtraOperations
/**
* 取得當前Activity
*/
fun peek(): Activity? {
return if (null != topActivity.get()) {
topActivity.get()
} else {
STACK.peekFromStack()
}
}
/**
* 關閉當前Activity
*/
fun pop() {
STACK.popFromStack()?.finish()
}
/**
* 關閉直到給定的Activity
*/
fun <T : Activity?> popUntil(clazz: Class<T>?): T? {
if (clazz != null) {
while (!STACK.isEmpty()) {
val activity = STACK.popFromStack()
if (activity != null) {
if (clazz.name == activity.javaClass.name) {
return activity as T
}
activity.finish()
}
}
}
return null
}
/**
* 關閉後的清理狀態
*/
private const val MAX_DOUBLE_EXIT_MILLS = 1000L
private var lastExitPressedMills = 0L
interface ExtraOperations {
fun onExit()
fun onActivityFinish(activity: Activity)
}
fun setOperations(operations: ExtraOperations) {
this.operations = operations
}
fun onExit() {
val now = System.currentTimeMillis()
if (now <= lastExitPressedMills + MAX_DOUBLE_EXIT_MILLS) {
finishAll()
operations.onExit()
exitProcess(0)
} else {
lastExitPressedMills = now
}
}
/**
* 關閉全部Activity
*/
private fun finishAll() {
while (!STACK.isEmpty()) {
val activity = STACK.popFromStack()
activity?.apply {
finish()
operations.onActivityFinish(this)
}
}
}
fun setTopActivity(topActivity: Activity) {
this.topActivity = WeakReference(topActivity)
}
fun push(activity: Activity) {
STACK.pushToStack(activity)
}
fun remove(activity: Activity) {
STACK.removeFromStack(activity)
}
private class ActivityStack {
private val activityStack = Stack<WeakReference<Activity>>()
fun isEmpty() = activityStack.isEmpty()
fun pushToStack(activity: Activity) {
activityStack.push(WeakReference(activity))
}
fun popFromStack(): Activity? {
while (!activityStack.isEmpty()) {
val weak = activityStack.pop()
val activity = weak.get()
if (activity != null) {
return activity
}
}
return null
}
fun peekFromStack(): Activity? {
while (!activityStack.isEmpty()) {
val weak = activityStack.peek()
val activity = weak.get()
if (activity != null) {
return activity
} else {
activityStack.pop()
}
}
return null
}
fun removeFromStack(activity: Activity) {
for (weak in activityStack) {
val act = weak.get()
if (act === activity) {
activityStack.remove(weak)
return
}
}
}
}
}
2.ActivityManage Application
MyApplication.kt
class MyApplication : Application() {
private val TAG = MyApplication::class.java.simpleName
var count = 0
override fun onCreate() {
super.onCreate()
registerActivityLifecycleCallbacks(object : ActivityLifecycleCallbacks {
override fun onActivityCreated(activity: Activity, savedInstanceState: Bundle?) {
ActivityManage.push(activity)
}
override fun onActivityStarted(activity: Activity) {
ActivityManage.setTopActivity(activity)
if (count++ == 0) {
Log.e(TAG, "前台")
}
}
override fun onActivityResumed(activity: Activity) {
}
override fun onActivityPaused(activity: Activity) {
}
override fun onActivityStopped(activity: Activity) {
count--
if (count == 0) {
Log.e(TAG, "後台")
}
}
override fun onActivitySaveInstanceState(activity: Activity, outState: Bundle) {
}
override fun onActivityDestroyed(activity: Activity) {
ActivityManage.remove(activity)
}
})
}
}
AndroidManifest.xml
<application
android:name=".MyApplication">
</application>
3.ActivityManage Activity
activity_first.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:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".FirstActivity">
<androidx.appcompat.widget.AppCompatButton
android:id="@+id/appCompatButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="next"
android:text="跳頁"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
FirstActivity.kt
class FirstActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
title = "First"
}
fun next(view: View) {
ActivityManage.peek()
?.startActivity(Intent(ActivityManage.peek(), SecondActivity::class.java))
}
}
activity_second.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:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".SecondActivity">
<androidx.appcompat.widget.AppCompatButton
android:id="@+id/appCompatButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="next"
android:text="跳頁"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
SecondActivity.kt
class SecondActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_second)
title = "Second"
}
fun next(view: View) {
ActivityManage.peek()
?.startActivity(Intent(ActivityManage.peek(), ThirdActivity::class.java))
}
}
5.ActivityManage pop
activity_third.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:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".ThirdActivity">
<androidx.appcompat.widget.AppCompatButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="finish"
android:text="結束"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
ThirdActivity.kt
class ThirdActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_third)
title = "Third"
}
fun finish(view: View) {
ActivityManage.pop()
}
}
6.ActivityManage popUntil
ThirdActivity.kt
class ThirdActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_third)
title = "Third"
}
fun finish(view: View) {
ActivityManage.popUntil(FirstActivity::class.java)
}
}
7.ActivityManage onExit
ThirdActivity.kt
class ThirdActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_third)
title = "Third"
}
fun finish(view: View) {
ActivityManage.setOperations(object : ActivityManage.ExtraOperations {
override fun onExit() {
Log.e(ThirdActivity::class.java.simpleName, "onExit")
}
override fun onActivityFinish(activity: Activity) {
Log.e(ThirdActivity::class.java.simpleName, activity.localClassName)
}
})
ActivityManage.onExit()
}
}