Activity详解

``

js 复制代码

一、Activity生命周期

1.1 什么是Activity

Activity即活动,是Android四大组件之一,是用户可视化的界面,界面中放置各种UI组件给用户操作及展示信息。

1.2 Activity的四种状态

1、running:运行中,当前界面在屏幕中可见且可操作。

2、paused:暂停中,当前界面可见但不可操作,例如出现一个弹框让该界面其他操作不可用。

3、stopped:停止中,不可见,被另一个界面完全覆盖,例如按下了Home键。

4、killed:退出,界面完全销毁。

1.3 进程优先级

1、前台:相当于状态中的运行,界面可见可操作。

2、可见:相当于状态中的暂停,界面可见不可操作。

3、服务:提供服务。

4、后台:相当于状态中的停止,界面不可见。

5、空:Activiy被回收。

1.4 生命周期

我们这里直接以官网图片来看,后面根据图并结合代码来看:【官网图片

我们先来对生命周期的每个阶段进行说明:

onCreate(): 在创建Activity时,我们必须实现该方法,他会在首次创建Activity时触发,此时Activity处于"已创建"。

onStart(): 执行完该方法后,Activity处于"可见"状态,即"已开始"

onResume(): 执行完该方法后,Activity处于"已恢复",可与用户进行交互。若没有其他操作界面会长时间处于该方法执行后的状态。

onPause(): 用户即将离开Activity时首先执行的方法。执行后Activity将处于"已暂停",不会在前台展示,但任然处于可见状态。当用户由该"已暂停"状态再次变为可操作的"已恢复"状态时会重新执行onResume().

onStop(): 若Activity即将不可见时执行的方法,之后Activity处于"已停止"。当用户由不可见变为可见可操作状态时,通过onRestart()回到onStart()再次执行。

onDestroy(): Activity销毁之前执行的方法,之后Activity处于"已销毁"。

系统终止进程的可能性 进程状态 Activity 状态
较小 前台(拥有或即将获得焦点) 已创建|已开始|已恢复
较大 后台(失去焦点) 已暂停
最大 后台(不可见) 已停止
已销毁

1.5 代码实战

我们先创建一个Activity并重写上面的各个方法,通过日志的打印来跟踪。

java 复制代码
package com.hczn.activitydemo;

import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle;
import android.util.Log;

public class MainActivity extends AppCompatActivity {
  private static final String TAG = "MainActivity";

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main); // 引入的布局资源
    Log.i(TAG, "进入了MainActivity的onCreate方法");
  }

  @Override
  protected void onStart() {
    super.onStart();
    Log.i(TAG, "进入了MainActivity的onStart方法");
  }

  @Override
  protected void onResume() {
    super.onResume();
    Log.i(TAG, "进入了MainActivity的onResume方法");
  }

  @Override
  protected void onRestart() {
    super.onRestart();
    Log.i(TAG, "进入了MainActivity的onReStart方法");
  }

  @Override
  protected void onPause() {
    super.onPause();
    Log.i(TAG, "进入了MainActivity的onPause方法");
  }

  @Override
  protected void onStop() {
    super.onStop();
    Log.i(TAG, "进入了MainActivity的onStop方法");
  }

  @Override
  protected void onDestroy() {
    super.onDestroy();
    Log.i(TAG, "进入了MainActivity的onDestroy方法");
  }
}

我们启动App并观察下控制台打印内容:

shell 复制代码
// ----- ① ------
// ... 
I/MainActivity: 进入了MainActivity的onCreate方法
I/MainActivity: 进入了MainActivity的onStart方法
    进入了MainActivity的onResume方法
// ...

我们按下Home建并观察控制台:

shell 复制代码
// ----- ① ------
// ...
I/MainActivity: 进入了MainActivity的onCreate方法
I/MainActivity: 进入了MainActivity的onStart方法
    进入了MainActivity的onResume方法
// ... 
// ----- ② -----
I/MainActivity: 进入了MainActivity的onPause方法
// ...
I/MainActivity: 进入了MainActivity的onStop方法

我们再次进入App中,观察控制台:

shell 复制代码
// ----- ① ------
// ...
I/MainActivity: 进入了MainActivity的onCreate方法
I/MainActivity: 进入了MainActivity的onStart方法
    进入了MainActivity的onResume方法
// ...
// ----- ② -----
I/MainActivity: 进入了MainActivity的onPause方法
// ...
I/MainActivity: 进入了MainActivity的onStop方法

// ----- ③ -----
I/MainActivity: 进入了MainActivity的onReStart方法
    进入了MainActivity的onStart方法
    进入了MainActivity的onResume方法
// ...

通过点击返回按键关闭Activity,观察控制台:

shell 复制代码
// ----- ① ------
// ...
I/MainActivity: 进入了MainActivity的onCreate方法
I/MainActivity: 进入了MainActivity的onStart方法
    进入了MainActivity的onResume方法
// ...
// ----- ② -----
I/MainActivity: 进入了MainActivity的onPause方法
// ...
I/MainActivity: 进入了MainActivity的onStop方法

// ----- ③ -----
I/MainActivity: 进入了MainActivity的onReStart方法
    进入了MainActivity的onStart方法
    进入了MainActivity的onResume方法
// ...
// ----- ④ -----
I/MainActivity: 进入了MainActivity的onPause方法
I/MainActivity: 进入了MainActivity的onStop方法
I/MainActivity: 进入了MainActivity的onDestroy方法

二、Android任务栈

2.1 说明

我们还是以官网的一张图来说明:

Android中的每个Activity任务是由一个栈来维护的,一开始为空,当我们打开App时,主界面就是第一个Activity,并加入到栈中且在栈顶。当由该Activity跳转到另一个Activity时,另一个Activity继续进入栈中;以此类推。当我们按下返回键时,处于栈顶的Activity出栈并销毁。直到退出App。

2.2 代码实战

在前面代码的基础上我们新建一个Activity并添加一个Activity跳转按钮。

activity_main.xml:

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=".MainActivity">

  <Button
    android:id="@+id/openOtherActivity"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="跳转到另一个界面"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintLeft_toLeftOf="parent"
    app:layout_constraintRight_toRightOf="parent"
    app:layout_constraintTop_toTopOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>

MainActivity.java:

java 复制代码
// ...
import android.widget.Button;

public class MainActivity extends AppCompatActivity {
  private static final String TAG = "MainActivity";

  Button openOtherActivity;

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    // ...
    openOtherActivity = findViewById(R.id.openOtherActivity);
  }

  @Override
  protected void onStart() {
    // ...
    openOtherActivity.setOnClickListener(v -> startActivity(new Intent(this, MainActivity2.class)));
  }
    
  // ...
}

我们运行App,点击主界面会跳转到另一个界面,再次按下返回键,观察控制台:

shell 复制代码
# 下面为点击跳转界面按钮的打印
# ...
I/MainActivity: 进入了MainActivity的onPause方法
W/ActivityThread: handleWindowVisibility: no activity for token android.os.BinderProxy@87891e3
I/MainActivity2: 进入了MainActivity2的onCreate方法
I/MainActivity2: 进入了MainActivity2的onStart方法
I/MainActivity2: 进入了MainActivity2的onResume方法
# ...
I/MainActivity: 进入了MainActivity的onStop方法

# 下面为按下返回按键的打印
I/MainActivity2: 进入了MainActivity2的onPause方法
I/MainActivity: 进入了MainActivity的onReStart方法
    进入了MainActivity的onStart方法
I/MainActivity: 进入了MainActivity的onResume方法
# ...
I/MainActivity2: 进入了MainActivity2的onStop方法
I/MainActivity2: 进入了MainActivity2的onDestroy方法

三、Activity启动模式

3.1 standard(默认)

标准启动模式;每启动一个Activity都需要重新创建一个实例。

3.2 singleTop

栈顶复用模式;当启动的一个Activity实例和栈顶的Activity实例为同一个类型时,则不会重新创建。

3.3 singleTask

栈内复用模式;若任务栈中没有Activity实例则创建,若有该类型的Activity实例,则将该实例栈前面的Activity实例出栈,显示该Activity。

3.4 singleInstance

单例模式;同一类型的Activity只有一个实例,类似singleTask不过该Activity实例在另一个任务栈中。

3.5 代码实战

我们这里创建两个Activity,分别为ActivityA、ActivityB,在AndroidManifest.xml文件中通过android:launchMode="启动模式类型"属性修改并结合控制台来观察。

1、AndroidManifest.xml

xml 复制代码
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
  xmlns:tools="http://schemas.android.com/tools"
  package="com.hczn.activitydemo">

  <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/Theme.ActivityDemo">
    <!--<activity android:name=".ActivityA" android:launchMode="standard">--> <!--默认模式,可不设置-->
    <!--<activity android:name=".ActivityA" android:launchMode="singleTop">-->
    <activity android:name=".ActivityA" android:launchMode="singleTask">
      <intent-filter>
        <action android:name="android.intent.action.MAIN" />

        <category android:name="android.intent.category.LAUNCHER" />
      </intent-filter>
    </activity>
    <activity android:name=".ActivityC" />
    <activity android:name=".ActivityB" />
    <!--<activity android:name=".ActivityB" android:launchMode="singleInstance" />-->

    <activity android:name=".MainActivity2" />
    <activity android:name=".MainActivity">

    </activity>
  </application>

</manifest>

2、activity_a.xml

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=".ActivityA">

  <TextView
    android:id="@+id/showMessage"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="这是ActivityA"
    app:layout_constraintTop_toTopOf="parent"
    app:layout_constraintRight_toRightOf="parent"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintLeft_toLeftOf="parent" />

  <Button
    android:id="@+id/toActivityA"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="跳转到ActivityA"
    app:layout_constraintTop_toBottomOf="@id/showMessage"
    app:layout_constraintRight_toRightOf="parent"
    app:layout_constraintLeft_toLeftOf="parent" />

  <Button
    android:id="@+id/toActivityB"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="跳转到ActivityB"
    app:layout_constraintTop_toBottomOf="@id/toActivityA"
    app:layout_constraintRight_toRightOf="parent"
    app:layout_constraintLeft_toLeftOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>

3、ActivityA.java

java 复制代码
package com.hczn.activitydemo;

import androidx.appcompat.app.AppCompatActivity;

import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.widget.Button;

public class ActivityA extends AppCompatActivity {
  private static final String TAG = "ActivityA";

  Button toActivityA;
  Button toActivityB;

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_a);

    toActivityA = findViewById(R.id.toActivityA);
    toActivityB = findViewById(R.id.toActivityB);

    Log.i(TAG, "ActivityA.onCreate()...");
  }

  @Override
  protected void onStart() {
    super.onStart();

    toActivityA.setOnClickListener(v -> startActivity(new Intent(this, ActivityA.class)));
    toActivityB.setOnClickListener(v -> startActivity(new Intent(this, ActivityB.class)));
  }
}

4、activity_b.xml

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=".ActivityB">

  <TextView
    android:id="@+id/showMessage"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="这是ActivityB"
    app:layout_constraintTop_toTopOf="parent"
    app:layout_constraintRight_toRightOf="parent"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintLeft_toLeftOf="parent" />

  <Button
    android:id="@+id/toActivityA"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="跳转到ActivityA"
    app:layout_constraintTop_toBottomOf="@id/showMessage"
    app:layout_constraintRight_toRightOf="parent"
    app:layout_constraintLeft_toLeftOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>

5、ActivityB.java

java 复制代码
package com.hczn.activitydemo;

import androidx.appcompat.app.AppCompatActivity;

import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.widget.Button;

public class ActivityB extends AppCompatActivity {
  private static final String TAG = "ActivityB";

  Button toActivityA;

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_b);

    toActivityA = findViewById(R.id.toActivityA);

    Log.i(TAG, "ActivityB.onCreate()...");
  }

  @Override
  protected void onStart() {
    super.onStart();

    toActivityA.setOnClickListener(v -> startActivity(new Intent(this, ActivityA.class)));
  }
}

6、操作说明

若ActivityA为standard模式,在ActivityA中每次点击跳转到ActivityA中都会执行一次ActivityA中的onCreate()

若ActivityA为singleTop模式,在ActivityA中点击跳转到ActivityA中不会执行ActivityA中的onCreated();若先跳转到ActivityB,从ActivityB再跳转到ActivityA,此时会执行ActivityA中的onCreate()

若ActivityA为singleTask模式,在ActivityA中点击跳转到ActivityA中不会执行ActivityA中的onCreated();若先跳转到ActivityB,从ActivityB再跳转到ActivityA也不会执行ActivityA中的onCreated();点击返回按键直接退出了App不会回到ActivityB

设ActivityA为默认模式,ActivityB为singleInstance模式,从ActivityA跳转到ActivityB中,点击Home键,再进入App中,发现我们看到的不是ActivityB(若为默认模式我们看到的应该是ActivityB)。我们再次点击ActivityA中的跳转到ActivityB,发现ActivityB中的onCreate()不会执行

四、Scheme跳转协议

后面有时间单开一篇来说明。非常重要。

相关推荐
Devil枫24 分钟前
Kotlin高级特性深度解析
android·开发语言·kotlin
ChinaDragonDreamer26 分钟前
Kotlin:2.1.20 的新特性
android·开发语言·kotlin
雨白11 小时前
Jetpack系列(二):Lifecycle与LiveData结合,打造响应式UI
android·android jetpack
kk爱闹13 小时前
【挑战14天学完python和pytorch】- day01
android·pytorch·python
每次的天空14 小时前
Android-自定义View的实战学习总结
android·学习·kotlin·音视频
恋猫de小郭15 小时前
Flutter Widget Preview 功能已合并到 master,提前在体验毛坯的预览支持
android·flutter·ios
断剑重铸之日16 小时前
Android自定义相机开发(类似OCR扫描相机)
android
随心最为安16 小时前
Android Library Maven 发布完整流程指南
android
岁月玲珑16 小时前
【使用Android Studio调试手机app时候手机老掉线问题】
android·ide·android studio
还鮟20 小时前
CTF Web的数组巧用
android