活动的生命周期

活动的生命周期

返回栈

  • Android中的活动是可以层叠的。我们每启动一个新的活动,就会覆盖在原活动之上,然后点击Back键会销毁最上面的活动,下面的活动就会重新显示出来

  • Android其实是使用(Task)来管理系统的,一个任务就是一组存放在栈里的活动的集合,这个栈也被称作返回栈(Back Stack)。栈是一种后进先出的数据结构,在默认情况下,每当我们启动了一个新的活动,他会在返回栈中入栈,并处于栈顶的位置。每当按下Back键或者调用finish()方法去销毁一个活动时,处于栈顶的活动会出栈,这时前一个活动就会重新处于栈顶的位置。系统总是会将处于栈顶的活动显示给用户。

  • 返回栈工作示意图

在这里插入图片描述

活动状态

  1. 运行状态:当一个活动位于返回栈的栈顶时,这时活动就处于运行状态。系统最不愿意回收的就是处于运行状态的活动,因为这会带来非常差的用户体验
  2. 暂停状态:当一个活动不再处于栈顶位置,但仍然可见时,这时活动就进入了暂停状态
  3. 停止状态:当一个活动不再处于栈顶位置,并且完全不可见的时候,就进入了停止状态。系统仍然会为这种活动保存相应的状态和成员变量,但是这并不是完全可靠的,当其他地方需要内存是,处于停止状态的活动有可能会被系统回收
  4. 销毁状态:当一个活动从返回栈中移除后就变成了销毁状态。系统会最倾向于回收处于这种状态的活动,从而保证手机的内存充足

活动的生存期

#### Activity类中定义了7个回调方法,覆盖了活动生命周期的每一个环节
  • onCreate():每个活动都重写了这个方法,它会在活动第一次被创建的时候调用,在这个方法中完成活动的初始化操作,比如加载布局、绑定事件等
  • onStart():这个方法在活动由不可见变为可见的时候调用
  • onResume():这个方法在活动准备好和用户进行交互的时候调用。此时的活动一定处于返回栈的栈顶,并处于运行状态
  • onPause():这个方法在系统准备去启动或者恢复另一个活动的时候调用。通常会在这个方法中将一些消耗CPU的资源释放掉,以及保存一些关键数据,但这个方法的执行速度一定要快,不然会影响到新的栈顶活动的使用
  • onStop():这个方法早活动完全不可见的时候调用。他和onPause()方法的主要区别在于,如果启动的新活动是一个对话框的活动,那么onPause()方法会得到执行,而onStop()方法并不执行
  • onDestroy():这个方法在活动被销毁之前调用,之后活动的状态将变为销毁状态
  • onRestart():这个方法在活动由停止状态变为运行状态之前调用,也就是活动被重新启动了
以上7个方法中除了onRestart()方法,其他都是两两相对的,从而又可以将活动分为3种生存期:
  • 完整生存期:活动在 onCreate()方法onDestroy()方法之间所经历的,就是完整生存期。一般情况下在 onCreate()方法中完成各种初始化操作,而在onDestroy()方法中完成释放内存的操作
  • 可见生存期:活动在onStart()方法onStop()方法之间经历的,就是可见生存期。在可见生存期内,活动对于用户总是可见的,即便有可能无法和用户进行交互。我们可以通过这两个方法,合理的管理那些对用户可见的资源。比如在onStart()方法中对资源进行加载,而在onStop()方法中对资源进行释放,从而保证处于停止状态的活动不会占用过多内存
  • 前台生存期:活动在onSesume()方法onPause()方法之间所经历的就是前台生存期。在前台生存期内,活动总是处于运行状态的,此时的活动是可以和用户进行狡猾的,我们平时看到和接触最多的也就是这个状态下的活动
  • 活动生命周期示意图
    在这里插入图片描述

实例

//注册页面AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.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/Theme.ActivityLifeCycleTest">
        <!-- android:theme  用于给当前活动指定主题       这里是让DialogActivity活动使用对话框的主题-->
        <activity android:name=".DialogActivity" android:theme="@style/Theme.AppCompat.Dialog">

        </activity>
        <activity android:name=".NormalActivity" />
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>
</manifest>
                    
//应用布局activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<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_activity"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Start DialogActivity"/>
</LinearLayout>

//正常布局normal_layout.xml
<?xml version="1.0" encoding="utf-8"?>
<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>

//对话框布局dialog_layout.xml
<?xml version="1.0" encoding="utf-8"?>
<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>
        
 //正常布局活动 NormalActivity
package com.example.activitylifecycletest;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
public class NormalActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.normal_layout);
    }
}

//对话框活动DialogActivity
package com.example.activitylifecycletest;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
public class DialogActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.dialog_layout);
    }
}

//应用活动MainActivity
package com.example.activitylifecycletest;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Log.d("TAG", "onCreate");
        setContentView(R.layout.activity_main);
        Button startNormalActivity = (Button) findViewById(R.id.start_normal_activity);
        Button startDialogActivity = (Button) findViewById(R.id.start_dialog_activity);
        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 intent1 = new Intent(MainActivity.this,DialogActivity.class);
                startActivity(intent1);
            }
        });
    }


    @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");
    }
    
    //总结
    //点击第一个按钮启动NormalActivity
    //当MainActivity第一次被创建时  先执行onCreate()、onStart()、onResume(),
    //点击第一个按钮,NormalActivity将MainActivity完全遮住,因此onPause()和onStop()得到执行
    //然后按下Back键,返回MainActivity,之前MainActivity已经进入了停止状态,所以onRestart()方法得到执行之后又依次执行onStart()和onResume()方法
    //注意:onCreate()没有被执行是因为MainActivity没有被重新创建


    //点击第二个按钮,启动DialogActivity
    //DialogActivity并没有将MainActivity完全覆盖,MainActivity只是进入了暂停状态,并没有进入停止状态,所以只执行onPause()方法
    //按下Back键返回MainActivity也只有onResume()方法执行

    //在MainActivity按Back键,会依次执行onPause()、onStop()、onDestroy(),最终销毁MainActivity


}

活动被回收了怎么办

  • 当一个活动进入到停止状态,是有可能被回收的

  • 比如:有一个活动A,在A的基础上启动活动B,A就会进入停止状态,这个时候由于内存不足,将A回收掉了,这是用户按Back键返回活动A。这时还是会正常显示A,只不过不会执行onRestart()方法,而是会执行活动A的onCreate方法,因为在这种情况下,活动A会被重新创建一次

  • 上述例子有一个重要问题,活动A中可能存在临时数据和状态,比如:MainActivity有一个文本输入框,现在你输入了一段文字,然后启动NormalActivity,这时MainActivity因为内存不足被回收,过了一会你又点击了Back键返回到MainActivity,你会发现刚刚输入的内容不见了,这是因为MainActivity被重新创建了

  • Activity提供了一个onSaveInstanceState()回调方法,可以解决活动被回收临时数据得不到保存的问题

  • onSaveInstanceState()方法会携带一个Bundle类型的参数,Bundle提供了一系列的方法用于保存数据,比如可以使用putString()方法保存字符串,使用putInt()方法保存整型数据,以此类推

  • 实例

    package com.example.activitylifecycletest;
    
    import androidx.annotation.NonNull;
    import androidx.annotation.Nullable;
    import androidx.appcompat.app.AppCompatActivity;
    
    import android.content.Intent;
    import android.os.Bundle;
    import android.util.Log;
    import android.view.View;
    import android.widget.Button;
    
    public class MainActivity extends AppCompatActivity {
    
        @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("data_key", tempData);
            }
            Button startNormalActivity = (Button) findViewById(R.id.start_normal_activity);
            Button startDialogActivity = (Button) findViewById(R.id.start_dialog_activity);
            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 intent1 = new Intent(MainActivity.this,DialogActivity.class);
                    startActivity(intent1);
                }
            });
    
        }
    
    
        @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");
        }
        
        
        @Override
        protected void onSaveInstanceState(Bundle outState) {
            super.onSaveInstanceState(outState);
            String tempData = "Something you just typed";
            outState.putString("data_key",tempData);
        }
    }
    
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值