{"id":1613,"date":"2022-12-13T13:55:32","date_gmt":"2022-12-13T05:55:32","guid":{"rendered":"https:\/\/badgameshow.com\/fly\/?p=1613"},"modified":"2022-12-13T13:56:05","modified_gmt":"2022-12-13T05:56:05","slug":"%e3%80%90util%e3%80%91activitymanage-activity-%e7%ae%a1%e7%90%86%e5%99%a8-%e7%af%84%e4%be%8b","status":"publish","type":"post","link":"https:\/\/badgameshow.com\/fly\/%e3%80%90util%e3%80%91activitymanage-activity-%e7%ae%a1%e7%90%86%e5%99%a8-%e7%af%84%e4%be%8b\/","title":{"rendered":"\u3010Util\u3011ActivityManage Activity \u7ba1\u7406\u5668 \u7bc4\u4f8b"},"content":{"rendered":"<h1>\u3010Util\u3011ActivityManage Activity \u7ba1\u7406\u5668 \u7bc4\u4f8b<\/h1>\n<h4>Android ActivityManage\uff0c\u662fAndroid\u5728\u61c9\u7528\u4e2d\u4f7f\u7528\u7684\u7ba1\u7406\u6d3b\u52d5\u7684\u7e7c\u627f\u6846\u67b6\u3002<\/h4>\n<h4>\u5b83\u80fd\u8b93Android\u958b\u767c\u8005\u5efa\u7acb\u53ef\u4ee5\u57f7\u884c\u9748\u6d3b\u6d3b\u52d5\u4e4b\u9593\u5207\u63db\uff0c\u7ba1\u7406\u9032\u5165\u53ca\u96e2\u958b\u6d3b\u52d5\uff0c\u6d3b\u52d5\u9593\u5207\u63db\u6642\u5019\u7684\u66ab\u505c\u53ca\u7e7c\u7e8c\u548c\u52a0\u8f09\u6d3b\u52d5\u53ca\u8cc7\u6e90\u7b49\u66f4\u70ba\u5b8c\u5584\u8207\u9748\u6d3b\u7684\u61c9\u7528\u3002<\/h4>\n<h4>\u672c\u6587\u5c07\u8aaa\u660eAndroid ActivityManage\u7684\u91cd\u8981\u6027\u53ca\u529f\u80fd\uff0c\u4e26\u4e14\u4ecb\u7d39\u5982\u4f55\u5be6\u73fe\u5b83\u4ee5\u53ca\u5b83\u5c0dAndroid\u61c9\u7528\u958b\u767c\u7684\u5f71\u97ff\u3002<\/h4>\n<hr \/>\n<h4>\u6587\u7ae0\u76ee\u9304<\/h4>\n<ol>\n<li><a href=\"#a\">ActivityManage<\/a><\/li>\n<li><a href=\"#b\">ActivityManage Application<\/a><\/li>\n<li><a href=\"#c\">ActivityManage Activity<\/a><\/li>\n<li><a href=\"#d\">ActivityManage pop<\/a><\/li>\n<li><a href=\"#e\">ActivityManage popUntil<\/a><\/li>\n<li><a href=\"#f\">ActivityManage onExit<\/a><\/li>\n<\/ol>\n<hr \/>\n<p><a id=\"a\"><\/a><\/p>\n<h4>1.ActivityManage<\/h4>\n<h5>ActivityManage.kt<\/h5>\n<pre><code class=\"language-kotlin line-numbers\">object ActivityManage {\n\n    private val STACK = ActivityStack()\n    private lateinit var topActivity: WeakReference&lt;Activity&gt;\n    private lateinit var operations: ExtraOperations\n\n    \/**\n     * \u53d6\u5f97\u7576\u524dActivity\n     *\/\n    fun peek(): Activity? {\n        return if (null != topActivity.get()) {\n            topActivity.get()\n        } else {\n            STACK.peekFromStack()\n        }\n    }\n\n    \/**\n     * \u95dc\u9589\u7576\u524dActivity\n     *\/\n    fun pop() {\n        STACK.popFromStack()?.finish()\n    }\n\n    \/**\n     * \u95dc\u9589\u76f4\u5230\u7d66\u5b9a\u7684Activity\n     *\/\n    fun &lt;T : Activity?&gt; popUntil(clazz: Class&lt;T&gt;?): T? {\n        if (clazz != null) {\n            while (!STACK.isEmpty()) {\n                val activity = STACK.popFromStack()\n                if (activity != null) {\n                    if (clazz.name == activity.javaClass.name) {\n                        return activity as T\n                    }\n                    activity.finish()\n                }\n            }\n        }\n        return null\n    }\n\n    \/**\n     * \u95dc\u9589\u5f8c\u7684\u6e05\u7406\u72c0\u614b\n     *\/\n    private const val MAX_DOUBLE_EXIT_MILLS = 1000L\n    private var lastExitPressedMills = 0L\n\n    interface ExtraOperations {\n        fun onExit()\n        fun onActivityFinish(activity: Activity)\n    }\n\n    fun setOperations(operations: ExtraOperations) {\n        this.operations = operations\n    }\n\n    fun onExit() {\n        val now = System.currentTimeMillis()\n        if (now &lt;= lastExitPressedMills + MAX_DOUBLE_EXIT_MILLS) {\n            finishAll()\n            operations.onExit()\n            exitProcess(0)\n        } else {\n            lastExitPressedMills = now\n        }\n    }\n\n    \/**\n     * \u95dc\u9589\u5168\u90e8Activity\n     *\/\n    private fun finishAll() {\n        while (!STACK.isEmpty()) {\n            val activity = STACK.popFromStack()\n            activity?.apply {\n                finish()\n                operations.onActivityFinish(this)\n            }\n        }\n    }\n\n    fun setTopActivity(topActivity: Activity) {\n        this.topActivity = WeakReference(topActivity)\n    }\n\n    fun push(activity: Activity) {\n        STACK.pushToStack(activity)\n    }\n\n    fun remove(activity: Activity) {\n        STACK.removeFromStack(activity)\n    }\n\n    private class ActivityStack {\n        private val activityStack = Stack&lt;WeakReference&lt;Activity&gt;&gt;()\n\n        fun isEmpty() = activityStack.isEmpty()\n\n        fun pushToStack(activity: Activity) {\n            activityStack.push(WeakReference(activity))\n        }\n\n        fun popFromStack(): Activity? {\n            while (!activityStack.isEmpty()) {\n                val weak = activityStack.pop()\n                val activity = weak.get()\n                if (activity != null) {\n                    return activity\n                }\n            }\n            return null\n        }\n\n        fun peekFromStack(): Activity? {\n            while (!activityStack.isEmpty()) {\n                val weak = activityStack.peek()\n                val activity = weak.get()\n                if (activity != null) {\n                    return activity\n                } else {\n                    activityStack.pop()\n                }\n            }\n            return null\n        }\n\n        fun removeFromStack(activity: Activity) {\n            for (weak in activityStack) {\n                val act = weak.get()\n                if (act === activity) {\n                    activityStack.remove(weak)\n                    return\n                }\n            }\n        }\n    }\n}\n<\/code><\/pre>\n<p><a id=\"b\"><\/a><\/p>\n<h4>2.ActivityManage Application<\/h4>\n<h5>MyApplication.kt<\/h5>\n<pre><code class=\"language-kotlin line-numbers\">class MyApplication : Application() {\n\n    private val TAG = MyApplication::class.java.simpleName\n    var count = 0\n\n    override fun onCreate() {\n        super.onCreate()\n\n        registerActivityLifecycleCallbacks(object : ActivityLifecycleCallbacks {\n            override fun onActivityCreated(activity: Activity, savedInstanceState: Bundle?) {\n                ActivityManage.push(activity)\n            }\n\n            override fun onActivityStarted(activity: Activity) {\n                ActivityManage.setTopActivity(activity)\n                if (count++ == 0) {\n                    Log.e(TAG, \"\u524d\u53f0\")\n                }\n            }\n\n            override fun onActivityResumed(activity: Activity) {\n\n            }\n\n            override fun onActivityPaused(activity: Activity) {\n\n            }\n\n            override fun onActivityStopped(activity: Activity) {\n                count--\n                if (count == 0) {\n                    Log.e(TAG, \"\u5f8c\u53f0\")\n                }\n            }\n\n            override fun onActivitySaveInstanceState(activity: Activity, outState: Bundle) {\n\n            }\n\n            override fun onActivityDestroyed(activity: Activity) {\n                ActivityManage.remove(activity)\n            }\n        })\n    }\n}\n<\/code><\/pre>\n<h5>AndroidManifest.xml<\/h5>\n<pre data-language=XML><code class=\"language-markup line-numbers\">&lt;application\n    android:name=\".MyApplication\"&gt;\n&lt;\/application&gt;\n<\/code><\/pre>\n<p><a id=\"c\"><\/a><\/p>\n<h4>3.ActivityManage Activity<\/h4>\n<h5>activity_first.xml<\/h5>\n<pre data-language=XML><code class=\"language-markup line-numbers\">&lt;?xml version=\"1.0\" encoding=\"utf-8\"?&gt;\n&lt;androidx.constraintlayout.widget.ConstraintLayout xmlns:android=\"http:\/\/schemas.android.com\/apk\/res\/android\"\n    xmlns:app=\"http:\/\/schemas.android.com\/apk\/res-auto\"\n    xmlns:tools=\"http:\/\/schemas.android.com\/tools\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\"\n    tools:context=\".FirstActivity\"&gt;\n\n    &lt;androidx.appcompat.widget.AppCompatButton\n        android:id=\"@+id\/appCompatButton\"\n        android:layout_width=\"wrap_content\"\n        android:layout_height=\"wrap_content\"\n        android:onClick=\"next\"\n        android:text=\"\u8df3\u9801\"\n        app:layout_constraintBottom_toBottomOf=\"parent\"\n        app:layout_constraintEnd_toEndOf=\"parent\"\n        app:layout_constraintStart_toStartOf=\"parent\"\n        app:layout_constraintTop_toTopOf=\"parent\" \/&gt;\n\n&lt;\/androidx.constraintlayout.widget.ConstraintLayout&gt;\n<\/code><\/pre>\n<h5>FirstActivity.kt<\/h5>\n<pre><code class=\"language-kotlin line-numbers\">class FirstActivity : AppCompatActivity() {\n\n    override fun onCreate(savedInstanceState: Bundle?) {\n        super.onCreate(savedInstanceState)\n        setContentView(R.layout.activity_main)\n\n        title = \"First\"\n    }\n\n    fun next(view: View) {\n        ActivityManage.peek()\n            ?.startActivity(Intent(ActivityManage.peek(), SecondActivity::class.java))\n    }\n}\n<\/code><\/pre>\n<h5>activity_second.xml<\/h5>\n<pre data-language=XML><code class=\"language-markup line-numbers\">&lt;?xml version=\"1.0\" encoding=\"utf-8\"?&gt;\n&lt;androidx.constraintlayout.widget.ConstraintLayout xmlns:android=\"http:\/\/schemas.android.com\/apk\/res\/android\"\n    xmlns:app=\"http:\/\/schemas.android.com\/apk\/res-auto\"\n    xmlns:tools=\"http:\/\/schemas.android.com\/tools\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\"\n    tools:context=\".SecondActivity\"&gt;\n\n    &lt;androidx.appcompat.widget.AppCompatButton\n        android:id=\"@+id\/appCompatButton\"\n        android:layout_width=\"wrap_content\"\n        android:layout_height=\"wrap_content\"\n        android:onClick=\"next\"\n        android:text=\"\u8df3\u9801\"\n        app:layout_constraintBottom_toBottomOf=\"parent\"\n        app:layout_constraintEnd_toEndOf=\"parent\"\n        app:layout_constraintStart_toStartOf=\"parent\"\n        app:layout_constraintTop_toTopOf=\"parent\" \/&gt;\n\n&lt;\/androidx.constraintlayout.widget.ConstraintLayout&gt;\n<\/code><\/pre>\n<h5>SecondActivity.kt<\/h5>\n<pre><code class=\"language-kotlin line-numbers\">class SecondActivity : AppCompatActivity() {\n\n    override fun onCreate(savedInstanceState: Bundle?) {\n        super.onCreate(savedInstanceState)\n        setContentView(R.layout.activity_second)\n\n        title = \"Second\"\n    }\n\n    fun next(view: View) {\n        ActivityManage.peek()\n            ?.startActivity(Intent(ActivityManage.peek(), ThirdActivity::class.java))\n    }\n}\n<\/code><\/pre>\n<p><a id=\"d\"><\/a><\/p>\n<h4>5.ActivityManage pop<\/h4>\n<h5>activity_third.xml<\/h5>\n<pre data-language=XML><code class=\"language-markup line-numbers\">&lt;?xml version=\"1.0\" encoding=\"utf-8\"?&gt;\n&lt;androidx.constraintlayout.widget.ConstraintLayout xmlns:android=\"http:\/\/schemas.android.com\/apk\/res\/android\"\n    xmlns:app=\"http:\/\/schemas.android.com\/apk\/res-auto\"\n    xmlns:tools=\"http:\/\/schemas.android.com\/tools\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\"\n    tools:context=\".ThirdActivity\"&gt;\n\n    &lt;androidx.appcompat.widget.AppCompatButton\n        android:layout_width=\"wrap_content\"\n        android:layout_height=\"wrap_content\"\n        android:onClick=\"finish\"\n        android:text=\"\u7d50\u675f\"\n        app:layout_constraintBottom_toBottomOf=\"parent\"\n        app:layout_constraintEnd_toEndOf=\"parent\"\n        app:layout_constraintStart_toStartOf=\"parent\"\n        app:layout_constraintTop_toTopOf=\"parent\" \/&gt;\n\n&lt;\/androidx.constraintlayout.widget.ConstraintLayout&gt;\n<\/code><\/pre>\n<h5>ThirdActivity.kt<\/h5>\n<pre><code class=\"language-kotlin line-numbers\">class ThirdActivity : AppCompatActivity() {\n\n    override fun onCreate(savedInstanceState: Bundle?) {\n        super.onCreate(savedInstanceState)\n        setContentView(R.layout.activity_third)\n\n        title = \"Third\"\n    }\n\n    fun finish(view: View) {\n        ActivityManage.pop()\n    }\n}\n<\/code><\/pre>\n<p><a id=\"e\"><\/a><\/p>\n<h4>6.ActivityManage popUntil<\/h4>\n<h5>ThirdActivity.kt<\/h5>\n<pre><code class=\"language-kotlin line-numbers\">class ThirdActivity : AppCompatActivity() {\n\n    override fun onCreate(savedInstanceState: Bundle?) {\n        super.onCreate(savedInstanceState)\n        setContentView(R.layout.activity_third)\n\n        title = \"Third\"\n    }\n\n    fun finish(view: View) {\n        ActivityManage.popUntil(FirstActivity::class.java)\n    }\n}\n<\/code><\/pre>\n<p><a id=\"f\"><\/a><\/p>\n<h4>7.ActivityManage onExit<\/h4>\n<h5>ThirdActivity.kt<\/h5>\n<pre><code class=\"language-kotlin line-numbers\">class ThirdActivity : AppCompatActivity() {\n\n    override fun onCreate(savedInstanceState: Bundle?) {\n        super.onCreate(savedInstanceState)\n        setContentView(R.layout.activity_third)\n\n        title = \"Third\"\n    }\n\n    fun finish(view: View) {\n        ActivityManage.setOperations(object : ActivityManage.ExtraOperations {\n            override fun onExit() {\n                Log.e(ThirdActivity::class.java.simpleName, \"onExit\")\n            }\n\n            override fun onActivityFinish(activity: Activity) {\n                Log.e(ThirdActivity::class.java.simpleName, activity.localClassName)\n            }\n        })\n\n        ActivityManage.onExit()\n    }\n}\n<\/code><\/pre>\n\n<div style=\"font-size: 0px; height: 0px; line-height: 0px; margin: 0; padding: 0; clear: both;\"><\/div>","protected":false},"excerpt":{"rendered":"<p>\u3010Util\u3011ActivityManage Activity \u7ba1\u7406\u5668 \u7bc4\u4f8b Android ActivityMa &hellip; <\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_monsterinsights_skip_tracking":false,"_monsterinsights_sitenote_active":false,"_monsterinsights_sitenote_note":"","_monsterinsights_sitenote_category":0,"pgc_sgb_lightbox_settings":"","footnotes":""},"categories":[9],"tags":[220,13,16],"class_list":["post-1613","post","type-post","status-publish","format-standard","hentry","category-util","tag-activitymanage","tag-android","tag-util"],"_links":{"self":[{"href":"https:\/\/badgameshow.com\/fly\/wp-json\/wp\/v2\/posts\/1613","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/badgameshow.com\/fly\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/badgameshow.com\/fly\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/badgameshow.com\/fly\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/badgameshow.com\/fly\/wp-json\/wp\/v2\/comments?post=1613"}],"version-history":[{"count":2,"href":"https:\/\/badgameshow.com\/fly\/wp-json\/wp\/v2\/posts\/1613\/revisions"}],"predecessor-version":[{"id":1621,"href":"https:\/\/badgameshow.com\/fly\/wp-json\/wp\/v2\/posts\/1613\/revisions\/1621"}],"wp:attachment":[{"href":"https:\/\/badgameshow.com\/fly\/wp-json\/wp\/v2\/media?parent=1613"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/badgameshow.com\/fly\/wp-json\/wp\/v2\/categories?post=1613"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/badgameshow.com\/fly\/wp-json\/wp\/v2\/tags?post=1613"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}