返回栈
Android的活动是可以重叠的。我们要启动一个新的活动,就会覆盖在原活动之上,然后点击Back键会销毁最上面的活动,下面的一个活动就会重新显示出来。其实Android是使用任务(Task)来管理活动的一个任务就是一组存放在栈里的活动的集合,这个栈也被称为返回栈(Back Stack)。栈是一种后进先出的数据结构,在默认情况下,每当我们启动了一个新的活动,他会在返回栈中入栈,并处于栈顶的位置。每当我们按下Back键或调用finish()方法去销毁一个活动时,处于栈顶的活动会出栈,系统总是会显示处于栈顶的活动给用户。
活动的状态
1、运行状态:当一个活动处于返回栈的栈顶时,这时活动就处于运行状态。此时系统不回收运行状态的活动。
2、暂停状态:当一个活动不再处于栈顶位置,但任然可见,这时活动就进入了暂停状态。系统不愿意回收这种活动,除非在内存极低的情况下,系统才会去考虑回收这种活动。
3、停止状态:当一个活动不再处于栈顶位置,并且完全不可见的时候,就进入了停止状态。当其他地方需要内存时,处于停止状态的活动有可能会被系统回收。
4、销毁状态:当一个活动从返回栈中移除后就变成了销毁状态。系统会回收这种状态。
活动的生存期
Activity类中定义了7个回调方法,覆盖了活动生命周期的每一个环节。
1、onCreate():在活动第一次被创建的时候调用,主要用来完成活动的初始化操作。如 加载布局,绑定事件等等。
2、onStart():在活动由不见变为可见的时候调用。
3、onResume():用来和用户交互。
4、onPause():这个方法在系统准备去启动或者恢复另一个活动的时候调用。
5、onStop():这个方法在活动完全不可见的时候调用。
6、onDestroy():这个方法在活动被销毁之前调用,之后活动的状态将变为销毁状态。
7、onRestart():在活动被重新被启动之前调用。
完整生存期: 活动在onCreate()方法和onDestroy()方法之间所经历的,就是完整生存期。
可见生存期:活动在onStart()方法和onStop()方法之间所经历的,在可见生存期内,活动对于用户总是可见的。
前台生存期:活动在onResume()方法和onPause()方法之间所经历的,活动总处于运行状态。
活动的生命周期
首先要新建一个项目,这里取名为ActivityLifeCycleTest。还要在创建两个子活动 NormalActivity和DialogActivity布局就取名为:normal_layout和dialog_layout。现在修改normal_layout.xml文件里面的代码。
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="This is a normal activity"
/>
</LinearLayout>
TextView:用于显示一行文字。
在修改dialog_layout.xml文件里面的代码。
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="This is a dialog activity"
/>
</LinearLayout>
该修改AndroidManifest.xml的<activity>标签的配置。
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.tw.flag.activitylifecycletest">
<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=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name=".NormalActivity" >
</activity>
<activity android:name=".DialogActivity"
android:theme="@style/Theme.AppCompat.Dialog">
</activity>
</application>
</manifest>
android:theme属性,用于给当前活动指定主题的,Android系统内置了很多主题可以选择,也可以自己定义。而这里的@style/Theme.AppCompat.Dialog 是让DialogActivity使用对话框式的主题。
接下来 来修改activity_main.xml里面的代码,重新定制主题活动的布局。
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<Button
android:id="@+id/start_normal_activity"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Start NormalActivity"/>
<Button
android:id="@+id/start_dialog_ativity"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Start DialogActivity"/>
</LinearLayout>
最后修改MainActivity中的代码。
package com.tw.flag.activitylifecycletest;
import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
public class MainActivity extends AppCompatActivity {
public static final String TAG="MainActivity";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.d(TAG,"onCreate");
setContentView(R.layout.activity_main);
if(savedInstanceState!=null){
String tempData=savedInstanceState.getString("data_key");
Log.d(TAG,tempData);
}
Button startNormalActivity=findViewById(R.id.start_normal_activity);
Button startDialogActivity=findViewById(R.id.start_dialog_ativity);
startNormalActivity.setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View v){
Intent intent=new Intent(MainActivity.this,NormalActivity.class);
startActivity(intent);
}
});
startDialogActivity.setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View v){
Intent intent =new Intent(MainActivity.this,DialogActivity.class);
startActivity(intent);
}
});
}
@Override
protected void onStart(){
super.onStart();
Log.d(TAG,"onStart");
}
@Override
protected void onResume(){
super.onResume();
Log.d(TAG,"OnResume");
}
@Override
protected void onPause(){
super.onPause();
Log.d(TAG,"onPause");
}
@Override
protected void onStop(){
super.onStop();
Log.d(TAG,"onStop");
}
@Override
protected void onDestroy(){
super.onDestroy();
Log.d(TAG,"onDestroy");
}
@Override
protected void onRestart(){
super.onRestart();
Log.d(TAG,"onRestart");
}
}
活动的启动模式
1、standard:是默认的启动模式在不进行显示的情况下,所有的活动都会自动启动这种模式。
如 修改FirstActivity中onCreate()方法中的代码。
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.d("FirstActivity","Task id is"+getTaskId());
setContentView(R.layout.first_layout);
Button button1 = findViewById(R.id.button_1);
button1.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.d("FirstActivity",this.toString());
setContentView(R.layout.first_layout);
Button button1 = findViewById(R.id.button_1);
button1.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.d("FirstActivity","Task id is"+getTaskId());
setContentView(R.layout.first_layout);
Button button1 = findViewById(R.id.button_1);
button1.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {Intent intent = new Intent(FirstActivity.this, FirstActivity.class);
startActivity(intent);
}
});
}
2、 singleTop当活动启动模式指定为singleTop,在启动活动时如果发现返回栈的栈顶已经是该活动,则认为可以直接使用它,不会再创建新的活动实例。修改AndroidManifest.xml中FirstActivity的启动模式.
<activity
android:name=".FirstActivity"
android:launchMode="singleTop"
android:label="This is FirstActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
修改FirstActivity中onCreate()方法中的代码。
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.d("FirstActivity","Task id is"+getTaskId());
setContentView(R.layout.first_layout);
Button button1 = findViewById(R.id.button_1);
button1.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.d("FirstActivity",this.toString());
setContentView(R.layout.first_layout);
Button button1 = findViewById(R.id.button_1);
button1.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.d("FirstActivity","Task id is"+getTaskId());
setContentView(R.layout.first_layout);
Button button1 = findViewById(R.id.button_1);
button1.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {Intent intent = new Intent(FirstActivity.this, SecondActivity.class);
startActivity(intent);
}
});
}
这次我们点击按钮启动的是SecondActivity。然后修改SecondActivity中onCreate()方法中的代码。
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.d("SecondActivity", this.toString());
setContentView(R.layout.second_layout);
Button button2 = findViewById(R.id.button_2);
button2.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) { Intent intent=new Intent(SecondActivity.this,FirstActivity.class);
startActivity(intent);
}
});
}
3、singleTask:当活动的启动模式指定为singleTask时,则每次启动时系统首先会在返回栈中检查是否存在该活动的实例。如果存在则直接使用该活动的实例,并把在这个活动之上的所有活动统统出栈。修改AndroidManifest.xml中FirstActivity的启动模式.
<activity
android:name=".FirstActivity"
android:launchMode="singleTask"
android:label="This is FirstActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
在 FirstActivity中添加onRestart()方法,并打印日志。
@Override
protected void onRestart() {
super.onRestart();
Log.d("FirstAcivity","onRestart");
}
}
4、singleInstance:是4种模式中最特殊最复杂的一个了。在这种模式下会用一个单独的返回栈来管理这个活动。
修改AndroidManifest.xml中SecondActivity的启动模式.
</activity>
<activity android:name=".SecondActivity"
android:launchMode="singleInstance">
<intent-filter>
<action android:name="com.example.activitytest.ACTION_START" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="com.example.activitytest.MY_CATEGORY" />
</intent-filter>
</activity>
修改FirstActivity中onCreate()方法中的代码。
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.d("FirstActivity","Task id is"+getTaskId());
setContentView(R.layout.first_layout);
Button button1 = findViewById(R.id.button_1);
button1.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(FirstActivity.this, SecondActivity.class);
startActivity(intent);
}
});
}
然后修改SecondActivity中onCreate()方法中的代码。
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.d("SecondActivity", "Task id is" + getTaskId());
setContentView(R.layout.second_layout);
Button button2 = findViewById(R.id.button_2);
button2.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent=new Intent(SecondActivity.this,ThirdActivity.class);
startActivity(intent);
}
});
}
最后修改ThirdActivity中onCreate()方法中的代码。
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.d("ThirdActivity","Task id is"+getTaskId());
setContentView(R.layout.third_layout);
Button button3=findViewById(R.id.button_3);
button3.setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View v) {
ActivityCollector.finishAll();
}
});