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")
}