Android Activity生命周期

面试:你懂什么是分布式系统吗?Redis分布式锁都不会?>>>   hot3.png

Android中Activity的生命周期,我今天特意在重新总结一下.
 

1大状态:

1.1 Running状态:

一个新的Activity启动入栈后,它在屏幕最前端,处于栈的最顶端,此时它处于可见并可和用户交互的激活状态。该状态activity位于task的最顶端

1.2 Paused状态:

当Activity被另一个透明或者Dialog样式的Activity覆盖时的状态。此时它依然与窗口管理器保持连接,系统继续维护其内部状态,它仍然可见,但它已经失去了焦点,故不可与用户交互。

如果一个Activity失去焦点,但是依然可见(一个新的非全屏的Activity 或者一个透明的Activity 被放置在栈顶),叫做暂停状态(Paused)。一个暂停状态的Activity依然保持活力(保持所有的状态,成员信息,和窗口管理器保持连接),但是在系统内存极端低下的时候将被杀掉。

1.3 Stopped状态:

当Activity不可见时,Activity处于Stopped状态。当Activity处于此状态时,一定要保存当前数据和当前的UI状态,否则一旦Activity退出或关闭时,当前的数据和UI状态就丢失了。

如果一个Activity被另外的Activity完全覆盖掉,叫做停止状态(Stopped)。它依然保持所有状态和成员信息,但是它不再可见,所以它的窗口被隐藏,当系统内存需要被用在其他地方的时候,Stopped的Activity将被杀掉。

1.4 Killed状态:

Activity被杀掉以后或者被启动以前,处于Killed状态。这是Activity已从Activity堆栈中移除,需要重新启动才可以显示和使用。

其中,Running状态和Paused状态是可见的,Stopped状态和Killed状态时不可见的。

Activity的重要状态转换,矩形框表明Activity在状态转换之间的回调接口,开发人员可以重载实现以便执行相关代码,带有颜色的椭圆形表明Activity所处的状态。

11

在上图中,Activity有三个关键的循环
(1)整个的生命周期,从onCreate(Bundle)开始到onDestroy()结束。Activity在onCreate()设置所有的“全局”状态,在onDestory()释放所有的资源。例如:某个Activity有一个在后台运行的线程,用于从网络下载数据,则该Activity可以在onCreate()中创建线程,在onDestory()中停止线程。
(2)可见的生命周期,从onStart()开始到onStop()结束。在这段时间,可以看到Activity在屏幕上,尽管有可能不在前台,不能和用户交互。在这两个接口之间,需要保持显示给用户的UI数据和资源等,例如:可以在onStart中注册一个IntentReceiver来监听数据变化导致UI的变动,当不再需要显示时候,可以在onStop()中注销它。onStart(),onStop()都可以被多次调用,因为Activity随时可以在可见和隐藏之间转换。
(3)前台的生命周期,从onResume()开始到onPause()结束。在这段时间里,该Activity处于所有 Activity的最前面,和用户进行交互。Activity可以经常性地在resumed和paused状态之间切换,例如:当设备准备休眠时,当一个 Activity处理结果被分发时,当一个新的Intent被分发时。所以在这些接口方法中的代码应该属于非常轻量级

注意点:

1,当用户打开新的Activity或者切换到桌面的时候,回调如下:onPause -> onStop,这里有一种特殊情况,如果新的Activity采用了透明的主题,那么当前Activity不会回调onStop。

2,onStart和onResume、onPause和onStop,有什么实质不同呢。

从Activity是否可见的角度看,onStart和onStop配对,从Activity是否位于前台这个角度,onResume和onPause配对。

3,假设当前Activity为A,如果这时用户打卡一个新的Activity B,那么B的onResume和A的onPause哪个先执行。

先会执行A的onPause后,新的Activity才能启动。官方文档中有这么一句,不能在onPause中做重量级的操作,因为必须onPause执行完成以后,新的Activity才能Resume。

异常情况下的生命周期分析

1,资源相关的系统配置发生改变导致Activity被杀死并重新创建。

比如当前Activity处于竖屏状态,突然横屏了,那么此时系统配置发生了改变,在默认情况下,Activity就会被销毁并且重新创建,拿的资源图片就会不一样,当系统配置发生变化之后,Activity会被销毁,其中onPause、onStop、onDestroy均会被调用,由于Activity是在异常情况下终止的,系统就会调用onSaveInstanceState来保存当前的Activity状态,这个方法是在onStop之前,它和onPause没有既定的时序关系,可能在onPause之前,也可能在onPause之后调用,需要强调下, 这个方法只会在Activity背异常终止的情况下调用,正常情况下系统不会回调这个方法。当Activity重新创建后,系统会调用onRestoreInstanceSate,并且把之前保存的数据恢复回来。

异常触发

关于保存和恢复View层次结构,系统的工作流程是这样的:首先Activity被意外终止时,Activity会调用onSaveInstanceState去保存数据,然后Activity会委托Window去保存数据,接着Window再委托它上面的顶级容器去保存数据,顶级容器是一个ViewGroup,一般来说它很可能是DecorView。最后顶层容器再去一一通知它的子元素来保存。这是一种典型的委托思想,上层委托下层,父容器委托子元素去处理一件事,这种思想在Android中很常见,比如View的绘制过程,事件分发等等。

总之,系统只有在Activity异常终止的情况下才会调用onSaveInstanceState和onRestoreInstanceSate来存储和恢复数据,其他情况下不会触发这个过程。

2,资源内存不足导致优先级低的Activity被杀死

Activity按照优先级从高到低,可以分为三种。

  1. 前台Activity—正在和用户交互的Activity,优先级最高
  2. 可见但非前台Activity—比如Activity中弹出了一个对话框,导致Activity可见但是位于后台无法和用户直接交互
  3. 后台Activity—已经被暂停的Activity,比如执行了onStop,优先级最低

当系统内存不足时,系统就会按照上述优先级去杀死目标Activity所在的进程,并后续通过onSaveInstanceState和onRestoreInstanceSate来存储和恢复数据,如果一个进程中没有四大组件在执行,那么这个进程将很快被系统杀死,因此,比较好的方法是将后台工作放入Service中从而保证进程有一定的优先级,这样就不会轻易地被系统杀死。

Activity其实是继承了ApplicationContext这个类,我们可以重写以下方法,如下代码:

 

view plaincopy to clipboardprint?
public class Activity extends ApplicationContext { 
       protected void onCreate(Bundle savedInstanceState); 
       protected void onStart();    
       protected void onRestart(); 
       protected void onResume(); 
       protected void onPause();  
       protected void onStop(); 
       protected void onDestroy(); 
   } 

为了便于大家更好的理解,我简单的写了一个Demo,不明白Activity周期的朋友们,可以亲手实践一下,大家按照我的步骤来。

第一步:新建一个Android工程,我这里命名为ActivityDemo.

第二步:修改ActivityDemo.java(我这里重新写了以上的七种方法,主要用Log打印),代码如下:

 

package com.tutor.activitydemo; 
import android.app.Activity; 
import android.os.Bundle; 
import android.util.Log; 
public class ActivityDemo extends Activity { 
    private static final String TAG = "ActivityDemo"; 
    public void onCreate(Bundle savedInstanceState) { 
        super.onCreate(savedInstanceState); 
        setContentView(R.layout.main); 
        Log.e(TAG, "start onCreate~~~"); 
    } 
    @Override 
    protected void onStart() { 
        super.onStart(); 
        Log.e(TAG, "start onStart~~~"); 
    } 
    @Override 
    protected void onRestart() { 
        super.onRestart(); 
        Log.e(TAG, "start onRestart~~~"); 
    } 
    @Override 
    protected void onResume() { 
        super.onResume(); 
        Log.e(TAG, "start onResume~~~"); 
    } 
    @Override 
    protected void onPause() { 
        super.onPause(); 
        Log.e(TAG, "start onPause~~~"); 
    } 
    @Override 
    protected void onStop() { 
        super.onStop(); 
        Log.e(TAG, "start onStop~~~"); 
    } 
    @Override 
    protected void onDestroy() { 
        super.onDestroy(); 
        Log.e(TAG, "start onDestroy~~~"); 
    } 
} 

第三步:运行上述工程,效果图如下(没什么特别的):

核心在Logcat视窗里,如果你还不会用Logcat你可以看一下我的这篇文章 Log图文详解(Log.v,Log.d,Log.i,Log.w,Log.e),我们打开应用时先后执行了onCreate()->onStart()->onResume三个方法,看一下LogCat视窗如下:

BACK键:

当我们按BACK键时,我们这个应用程序将结束,这时候我们将先后调用onPause()->onStop()->onDestory()三个方法,如下图所示:

HOME键:

当我们打开应用程序时,比如浏览器,我正在浏览NBA新闻,看到一半时,我突然想听歌,这时候我们会选择按HOME键,然后去打开音乐应用程序,而当我们按HOME的时候,Activity先后执行了onPause()->onStop()这两个方法,这时候应用程序并没有销毁。如下图所示:

而当我们再次启动ActivityDemo应用程序时,则先后分别执行了onRestart()->onStart()->onResume()三个方法,如下图所示:

这里我们会引出一个问题,当我们按HOME键,然后再进入ActivityDemo应用时,我们的应用的状态应该是和按HOME键之前的状态是一样的,同样为了方便理解,在这里我将ActivityDemo的代码作一些修改,就是增加一个EditText。

第四步:修改main.xml布局文件(增加了一个EditText),代码如下:

<?xml version="1.0" encoding="utf-8"?> 
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
     android:orientation="vertical" 
     android:layout_width="fill_parent" 
     android:layout_height="fill_parent" 
     > 
<TextView   
     android:layout_width="fill_parent"  
     android:layout_height="wrap_content"  
     android:text="@string/hello" 
     /> 
<EditText 
     android:id="@+id/editText" 
     android:layout_width="fill_parent" 
     android:layout_height="wrap_content" 
/> 
</LinearLayout> 

第五步:然后其他不变,运行ActivityDemo程序,在EditText里输入如"Frankie"字符串(如下图:)

这时候,大家可以按一下HOME键,然后再次启动ActivityDemo应用程序,这时候EditText里并没有我们输入的"Frankie"字样,如下图:

这显然不能称得一个合格的应用程序,所以我们需要在Activity几个方法里自己实现,如下第六步所示:

第六步修改ActivityDemo.java代码如下:

 

package com.tutor.activitydemo; 
import android.app.Activity; 
import android.os.Bundle; 
import android.util.Log; 
import android.widget.EditText; 
public class ActivityDemo extends Activity { 
     private static final String TAG = "ActivityDemo"; 
     private EditText mEditText; 
     //定义一个String 类型用来存取我们EditText输入的值 
     private String mString; 
     public void onCreate(Bundle savedInstanceState) { 
         super.onCreate(savedInstanceState); 
         setContentView(R.layout.main); 
         mEditText = (EditText)findViewById(R.id.editText); 
         Log.e(TAG, "start onCreate~~~"); 
     } 
     @Override 
     protected void onStart() { 
         super.onStart(); 
         Log.e(TAG, "start onStart~~~"); 
     } 
     //当按HOME键时,然后再次启动应用时,我们要恢复先前状态 
     @Override 
     protected void onRestart() { 
         super.onRestart(); 
         mEditText.setText(mString); 
         Log.e(TAG, "start onRestart~~~"); 
     }  
     @Override 
     protected void onResume() { 
         super.onResume(); 
         Log.e(TAG, "start onResume~~~"); 
     } 
     //当我们按HOME键时,我在onPause方法里,将输入的值赋给mString 
     @Override 
     protected void onPause() { 
         super.onPause(); 
         mString = mEditText.getText().toString(); 
         Log.e(TAG, "start onPause~~~"); 
     }  
     @Override 
     protected void onStop() { 
         super.onStop(); 
         Log.e(TAG, "start onStop~~~"); 
     } 
     @Override 
     protected void onDestroy() { 
         super.onDestroy(); 
         Log.e(TAG, "start onDestroy~~~"); 
     } 
} 

第七步:重新运行ActivityDemo程序,重复第五步操作,当我们按HOME键时,再次启动应用程序时,EditText里有上次输入的"Frankie"字样,如下图如示:

OK,大功基本告成,这时候大家可以在回上面看一下Activity生命周期图,我想大家应该完全了解了Activity的生命周期了,不知道你了解了没?

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Android中的Activity生命周期包括以下几个方法:onCreate、onStart、onResume、onPause、onStop和onDestroy。onCreate方法被调用时,表示Activity正在被创建,可以在这个方法中进行一些初始化操作。onStart方法在Activity即将变为可见状态时被调用,可以在这个方法中开始一些活动,如注册监听器等。onResume方法在Activity变为可见并且可以与用户进行交互之前被调用,可以在这个方法中开始一些动画、音乐等操作。onPause方法在Activity失去前台焦点、但仍然可见时被调用,可以在这个方法中暂停一些活动,如暂停动画、音乐等操作。onStop方法在Activity完全不可见时被调用,可以在这个方法中释放一些资源,如取消注册监听器等。onDestroy方法在Activity即将被销毁时被调用,可以在这个方法中进行一些回收工作,如释放资源。根据不同的情况,Activity生命周期的调用顺序可能有所不同,但是每个生命周期方法都有其特定的用途。例如,onPause和onResume方法通常是成对出现的,表示Activity失去前台焦点和重新获得前台焦点。总体而言,Activity生命周期的不同阶段可以用来管理资源的创建、释放和活动的状态切换等操作。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [【Android ActivityActivity生命周期](https://blog.csdn.net/qq_38350635/article/details/88855761)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值