Android學習筆記-Activity的啟動模式
Activity的啟動模式——standard
-
standard是Activity預設的啟動模式,在不進行顯式指定的情況下,所有Activity都會自動使用這種啟動模式。
-
在standard模式下,每當啟動一個新的Activity,它就會在返回棧中入棧,並處於棧頂的位置。
-
對於使用standard模式的Activity,系統不會在乎這個Activity是否已經在返回棧中存在,每次啟動都會建立一個該Activity的新例項。
程式碼演示,建立一個Activity,在該Activity中啟動一個新的Activity,啟動模式不設定(預設為standard
)
FirstActivity:
package com.easycol.reactivitylifecycle
import android.content.Intent
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.util.Log
import kotlinx.android.synthetic.main.activity_first.*
class FirstActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_first)
Log.d("FirstActivity", "FirstActivity onCreate")
button.setOnClickListener{
val intent = Intent(this, FirstActivity::class.java)
startActivity(intent)
}
}
override fun onStart() {
super.onStart()
Log.d("FirstActivity", "FirstActivity onStart")
}
override fun onResume() {
super.onResume()
Log.d("FirstActivity", "FirstActivity onResume")
}
}
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">
<TextView
android:id="@+id/text"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
android:layout_marginLeft="15dp"
android:layout_marginTop="15dp"
android:textSize="20dp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:textAlignment="center"
android:textColor="@color/colorPrimaryDark"
android:text="第一個頁面"/>
<Button
android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintTop_toBottomOf="@+id/text"
android:layout_marginTop="15dp"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
android:textAllCaps="false"
android:text="啟動一個另一個FirstActivity"
android:textSize="20dp"
android:textColor="@color/colorPrimaryDark"/>
</androidx.constraintlayout.widget.ConstraintLayout>
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.easycol.reactivitylifecycle">
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".FirstActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
啟動程式:
2020-10-01 17:41:16.917 26751-26751/com.easycol.reactivitylifecycle D/FirstActivity: FirstActivity onCreate
2020-10-01 17:41:16.927 26751-26751/com.easycol.reactivitylifecycle D/FirstActivity: FirstActivity onStart
2020-10-01 17:41:16.933 26751-26751/com.easycol.reactivitylifecycle D/FirstActivity: FirstActivity onResume
刪除列印,點選按鈕:
2020-10-01 17:42:27.036 26751-26751/com.easycol.reactivitylifecycle D/FirstActivity: FirstActivity onCreate
2020-10-01 17:42:27.046 26751-26751/com.easycol.reactivitylifecycle D/FirstActivity: FirstActivity onStart
2020-10-01 17:42:27.048 26751-26751/com.easycol.reactivitylifecycle D/FirstActivity: FirstActivity onResume
說明新建立了一個Activity。
Activity的啟動模式——singleTop
- 當Activity的啟動模式指定為singleTop,在啟動Activity時如果發現返回棧的棧頂已經是該Activity,則認為可以直接使用它,不會再建立新的Activity例項。
還是剛才的程式碼,設定FirstActivity的啟動模式為singleTop
<activity android:name=".FirstActivity"
android:launchMode="singleTop">
啟動程式:
2020-10-01 17:45:53.303 26965-26965/com.easycol.reactivitylifecycle D/FirstActivity: FirstActivity onCreate
2020-10-01 17:45:53.313 26965-26965/com.easycol.reactivitylifecycle D/FirstActivity: FirstActivity onStart
2020-10-01 17:45:53.316 26965-26965/com.easycol.reactivitylifecycle D/FirstActivity: FirstActivity onResume
刪除列印,點選按鈕:
2020-10-01 17:46:27.347 26965-26965/com.easycol.reactivitylifecycle D/FirstActivity: FirstActivity onResume
說明並沒有建立新的Activity
,複用了已經建立的FirstActivity
Activity的啟動模式——singleTask
- 當Activity的啟動模式指定為singleTask,每次啟動該Activity時,系統首先會在返回棧中檢查是否存在該Activity的例項,如果發現已經存在則直接使用該例項,並把在這個Activity之上的所有其他Activity統統出棧,如果沒有發現就會建立一個新的Activity例項。
程式碼演示:在前面程式碼的基礎上,新建一個Activity(SecondActivity
)
修改FirstActivity的程式碼,並設定FirstActivity的啟動模式為singleTask,程式碼如下:
FirstActivity
package com.easycol.reactivitylifecycle
import android.content.Intent
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.util.Log
import kotlinx.android.synthetic.main.activity_first.*
class FirstActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_first)
Log.d("FirstActivity", "FirstActivity onCreate")
button.setOnClickListener{
val intent = Intent(this, FirstActivity::class.java)
startActivity(intent)
}
button1.setOnClickListener{
val intent = Intent(this, SecondActivity::class.java)
startActivity(intent)
}
}
override fun onStart() {
super.onStart()
Log.d("FirstActivity", "FirstActivity onStart")
}
override fun onResume() {
super.onResume()
Log.d("FirstActivity", "FirstActivity onResume")
}
override fun onDestroy() {
super.onDestroy()
Log.d("FirstActivity", "FirstActivity onDestroy")
}
}
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">
<TextView
android:id="@+id/text"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
android:layout_marginLeft="15dp"
android:layout_marginTop="15dp"
android:textSize="20dp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:textAlignment="center"
android:textColor="@color/colorPrimaryDark"
android:text="第一個頁面"/>
<Button
android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintTop_toBottomOf="@+id/text"
android:layout_marginTop="15dp"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
android:textAllCaps="false"
android:text="啟動另一個FirstActivity"
android:textSize="20dp"
android:textColor="@color/colorPrimaryDark"/>
<Button
android:id="@+id/button1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintTop_toBottomOf="@+id/button"
android:layout_marginTop="15dp"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
android:layout_marginStart="15dp"
android:layout_marginLeft="15dp"
android:layout_marginRight="15dp"
android:textAllCaps="false"
android:text="啟動SecondActivity"
android:textSize="20dp"
android:textColor="@color/colorPrimaryDark"/>
</androidx.constraintlayout.widget.ConstraintLayout>
SecondActivity
package com.easycol.reactivitylifecycle
import android.content.Intent
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.util.Log
import kotlinx.android.synthetic.main.activity_first.*
class SecondActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_second)
Log.d("SecondActivity", "SecondActivity onCreate")
button.setOnClickListener{
val intent = Intent(this, FirstActivity::class.java)
startActivity(intent)
}
}
override fun onStart() {
super.onStart()
Log.d("SecondActivity", "SecondActivity onStart")
}
override fun onResume() {
super.onResume()
Log.d("SecondActivity", "SecondActivity onResume")
}
override fun onDestroy() {
super.onDestroy()
Log.d("SecondActivity", "SecondActivity onDestroy")
}
}
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">
<TextView
android:id="@+id/text"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
android:layout_marginLeft="15dp"
android:layout_marginTop="15dp"
android:textSize="20dp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:textAlignment="center"
android:textColor="@color/colorPrimaryDark"
android:text="第二個頁面"/>
<Button
android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintTop_toBottomOf="@+id/text"
android:layout_marginTop="15dp"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
android:textAllCaps="false"
android:text="啟動FirstActivity"
android:textSize="20dp"
android:textColor="@color/colorPrimaryDark"/>
</androidx.constraintlayout.widget.ConstraintLayout>
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.easycol.reactivitylifecycle">
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".SecondActivity"
android:launchMode="standard"></activity>
<activity
android:name=".FirstActivity"
android:launchMode="singleTask">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
啟動程式,點選啟動SecondActivity
按鈕
跳轉到SecondActivity
然後點選啟動FirstActivity
按鈕,檢視列印結果:
針對FirstActivity
:
2020-10-01 21:31:02.598 29467-29467/com.easycol.reactivitylifecycle D/FirstActivity: FirstActivity onCreate
2020-10-01 21:31:02.617 29467-29467/com.easycol.reactivitylifecycle D/FirstActivity: FirstActivity onStart
2020-10-01 21:31:02.626 29467-29467/com.easycol.reactivitylifecycle D/FirstActivity: FirstActivity onResume
2020-10-01 21:31:08.089 29467-29467/com.easycol.reactivitylifecycle D/FirstActivity: FirstActivity onStart
2020-10-01 21:31:08.091 29467-29467/com.easycol.reactivitylifecycle D/FirstActivity: FirstActivity onResume
針對SecondActivity
:
2020-10-01 21:34:12.367 29568-29568/com.easycol.reactivitylifecycle D/SecondActivity: SecondActivity onCreate
2020-10-01 21:34:12.377 29568-29568/com.easycol.reactivitylifecycle D/SecondActivity: SecondActivity onStart
2020-10-01 21:34:12.379 29568-29568/com.easycol.reactivitylifecycle D/SecondActivity: SecondActivity onResume
2020-10-01 21:34:14.751 29568-29568/com.easycol.reactivitylifecycle D/SecondActivity: SecondActivity onDestroy
- 在
SecondActivity
啟動FirstActivity
時,並沒有建立新的Activity,而是複用了已經建立的FirstActivity
,當點選系統返回按鈕時,程式直接退出。
Activity的啟動模式——singleInstance
-
當Activity的啟動模式指定為singleInstance,會啟用一個新的返回棧來管理這個Activity。
-
假設我們的程式中有一個Activity是允許其他程式呼叫的,如果想實現其他程式和我們的程式可以共享這個Activity的例項,就可以使用singleInstance模式。
-
在這種模式下,會有一個單獨的返回棧來管理這個Activity,不管是哪個應用程式來訪問這個Activity,都共用的同一個返回棧,也就解決了共享Activity例項的問題。
Kotlin課堂
標準函式with、run和apply
with函式接收兩個引數:第一個引數可以是一個任意型別的物件,第二個引數是一個Lambda表示式。with函式會在Lambda表示式中提供第一個引數物件的上下文,並使用Lambda表示式中的最後一行程式碼作為返回值返回。
示例程式碼如下:
val result = with(obj) {
// 這裡是obj的上下文
"value" // with函式的返回值
}
run函式的用法和使用場景其實和with函式是非常類似的,只是稍微做了一些語法改動而已。首先run函式是不能直接呼叫的,而是一定要呼叫某個物件的run函式才行;其次run函式只接收一個Lambda引數,並且會在Lambda表示式中提供呼叫物件的上下文。其他方面和with函式是一樣的,包括也會使用Lambda表示式中的最後一行程式碼作為返回值返回。
示例程式碼如下:
val result = obj.run {
// 這裡是obj的上下文
"value" // run函式的返回值
}
apply函式和run函式也是極其類似的,都是要在某個物件上呼叫,並且只接收一個Lambda引數,也會在Lambda表示式中提供呼叫物件的上下文,但是apply函式無法指定返回值,而是會自動返回撥用物件本身。
示例程式碼如下:
val result = obj.apply {
// 這裡是obj的上下文
}
// result == obj
定義靜態方法
Kotlin沒有直接定義靜態方法的關鍵字,但是提供了一些語法特性來支援類似於靜態方法呼叫的寫法,如單例類,companion object等,這些語法特性基本可以滿足我們平時的開發需求了。
然而如果你確確實實需要定義真正的靜態方法, Kotlin仍然提供了兩種實現方式:註解和頂層方法。
@JvmStatic註解
class Util {
companion object {
@JvmStatic
fun doAction() {
println("do action2")
}
}
}
頂層方法
fun doSomething() {
println("do something")
}
相關文章
- 【筆記】【Android】Activity的Task模式筆記Android模式
- Android-Activity的啟動模式Android模式
- 擼擼Android的羊毛(一)----Activity啟動模式Android模式
- Activity啟動模式模式
- Activity啟動模式(GIF 動態演示)模式
- Activity 的 "啟動流程"(基於 Android 9.0)Android
- Android中Activity的四種啟動方式Android
- Android 學習筆記雜記Android筆記
- Netty學習筆記(五)NioEventLoop啟動Netty筆記OOP
- 《Android原始碼設計模式》學習筆記之ImageLoaderAndroid原始碼設計模式筆記
- Android Studio學習筆記Android筆記
- Android Linker學習筆記Android筆記
- Android學習筆記·ANRAndroid筆記
- Android學習筆記·HandlerAndroid筆記
- Android學習筆記·ADBAndroid筆記
- Android學習筆記一Android筆記
- Android SQLite學習筆記AndroidSQLite筆記
- Android Activity啟動流程原始碼分析Android原始碼
- Android程式啟動與Activity顯示Android
- Android原始碼分析:Activity啟動流程Android原始碼
- Activity生命週期與啟動模式模式
- 組內技術分享-Activity 的啟動模式模式
- Android Activity是如何啟動的?Activity的生命週期是如何呼叫的?Android
- Android進階;Activity的棧與跳轉(筆記)Android筆記
- Android 開發藝術探索筆記之一 -- Android 的生命週期和啟動模式Android筆記模式
- Android 開發學習筆記Android筆記
- Android Gradle 學習筆記整理AndroidGradle筆記
- Android 學習筆記思考篇Android筆記
- Android 學習筆記核心篇Android筆記
- 2018.03.06 Android Handler學習筆記Android筆記
- 深入理解Android 之 Activity啟動流程(Android 10)Android
- 學習筆記-設計模式:MVC模式筆記設計模式MVC
- 設計模式學習筆記設計模式筆記
- 《SQL 反模式》 學習筆記SQL模式筆記
- 學習筆記-設計模式筆記設計模式
- Android 8.0 原始碼分析 (四) Activity 啟動Android原始碼
- Android黑科技:如何啟動未註冊的ActivityAndroid
- Android啟動模式Android模式