Activity啓動模式設置爲singleTask和singleInstance的問題

1、singleTask問題

假設我們App的啓動界面爲A,則在清單文件中應該是這樣的:

		<activity
			android:name=".A"
			android:launchMode="singleTask">
			<intent-filter>
				<action android:name="android.intent.action.MAIN" />
				<category android:name="android.intent.category.LAUNCHER" />
			</intent-filter>
		</activity>

然後我們會有B界面,C界面,D界面。。。

假設我們打開了B界面或者C界面或者D界面,除A以外的任意界面都可以,此時按Home鍵,使App處於後臺運行,然後在桌面上找到App的圖標並點擊打開,我們會發現App的界面顯示爲A界面,並沒有顯示我們之前後臺運行時的界面,經過打Log發現,除了A界面,其他的界面都會被銷燬。如果我們在App後臺運行時,長按Home,從最近任務中點開App,則可以回到原來的界面。這就很神奇了。

試了其他應用又不會這樣,對比發現是啓動模式的問題,lauchMode不設置的話默認爲standard,按我以前的理解,standard和singTask的作用是這樣的:

  • standard:每次調用startActivity()啓動時都會創建一個新的Activity放在棧頂(原來的Activity不會銷燬)
  • singleTask:如果啓動的Activity不存在就創建,如果存在直接跳轉到指定的Activity所在位置(即把它上面的所有Activity銷燬掉)

按着這個功能解釋的話,可以解釋一部分問題。當我們從最近任務中恢復app時,可以回到原來的應用,說明系統沒有啓動app的主界面,而當從桌面的圖標點擊恢復app時,系統則啓動了主界面,由於主界面設置了singleTask,所以主界面上面的所有界面就都會被銷燬。這麼理解似乎可以解釋問題的原因,但是換成standard時又解釋不通,換成standard後,從桌面點擊app圖標,如果系統是調用了startActivity開啓主界面的話,則應該會再創建一個新的主界面,主界面會置於棧頂,但是實際運行效果並不是,實際運行的效果點擊桌面圖標與從最近任務中恢復的效果是一樣的。

雖然沒搞清楚爲什麼會這樣,解決方案就是把啓動模式singleTask換成standard即可。

2、singleInstance問題

這個問題之前遇到,當時沒有即時記錄問題,現在大概記得是什麼問題,但是具體操作細節記不清了。

先說一下以前學習singleInstance時的理解:
singleInstance:如果啓動的Activity不存在就創建,如果存在就將指定的Activity移動到棧頂(原來它上面的所有Activity不會銷燬)
這裏少了一個理解,以這個模式開啓的Activity將會處於一個新的任務棧中,帶來的問題跟上面的差不多,就是後臺運行後,我不記得是從最近任務還是從桌面圖標中恢復了,會發現回不到之前的界面。

3、總結

  1. App的啓動界面不要設置爲singleTask,否則會導致後臺運行後每次從桌面點擊恢復時都回到啓動面的問題。App中的非啓動界面可以設置爲singleTask,不會導致後臺運行後回不到之前界面的問題。
  2. signleInstance導致多個任務棧,後臺運行後回不到之前界面的問題,那什麼時候用singleInstance呢,等我有時間了再來研究一下,現在我們知道它會帶來什麼問題也算是有所收穫了。

後續

後來工作又開發了一個新App,有一個主界面,程序一啓動就先打開主界面,而且主界面是一直存在不銷燬的,這樣的話,這個主界面的laucherMode使用SingleTask再合適不過了,但是他又會導致我們上面說的問題。

後來想出了一個解決辦法,新建一個空的Activity,啓動模式爲standard,這個Activity一啓動就開啓我們的主界面,並結束它自己,代碼如下:

<activity
	android:name=".module.LauncherActivity"
	android:screenOrientation="portrait"
	tools:ignore="LockedOrientationActivity"
	android:theme="@android:style/Theme.NoDisplay">
	<intent-filter>
		<action android:name="android.intent.action.MAIN" />
		<category android:name="android.intent.category.LAUNCHER" />
	</intent-filter>
</activity>
class LauncherActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        startActivity<MainActivity>()
        finish()
    }
}

OK,就是這麼簡單,這樣處理之後,點擊桌面圖標時就不會導致系統又給我們開啓主界面了!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章