重新认识Android Activity的生命周期

http://peiquan.blog.51cto.com/7518552/1277373


一、基础

 看了官方文档之后,自己领悟过来接着翻译的,由于第一次的原因,技术水品乜有跟上,还请大家将就将就。如果你有更好的建议的,希望你可以提出,如果你觉得哪里写的不好的,恳请留下你的指导意见,谢谢。

一、基础

   1.1自己创建的activity必须要继承类Activity(或其子类)。在activity里,为了实现activity各种状态的切换,你必须实现指定的回调方法。以下是最为重要的两个回调方法

      onCreate():

   这是必须实现的回调方法,启动一个 activity时会首先调用此方法。因此,在onCreate()的方法体里,你应该初始化该activity必要的控件。值得注意的是,在这里你必须调用setContentViewView view)方法去呈现用户的界面。

      onPause()

   在用户将要离开activity时调用此方法(指的是此时activity处于半透明状态且没有获取用户的焦点)。通常在这样的状态下,你需要处理用户数据的提交、动画处理等操作。

   1.2销毁activity

   你可以调用finish()方法去销毁一个activity。同样得,你可以调用finishActivity()方法去销毁一个你刚刚启动的activity

tips

在多数情况下,你是不需要显式地调用finish…()方法去销毁一个activity。在将要讨论到的activity生命周期里,你可以知道,Android系统会为你管理activity的生命周期,所以你并不需要显式销毁activity(即调用finish类方法)。显式地调用finish类方法,会对用户的体验产生不利的影响,除非你确实是不希望用户返回到此activity(界面),才去显式调用finish类方法。



二、认识activity的生命周期

21

  Activity的生命周期对它的任务、backstack和与此有关联的activity有着直接的影响。因此想开发出一个健壮的有弹性的Android程序,你需要学会如何去管理activity的生命周期(即调用各种回调方法)。

  activity的生命周期主要包含一些三种状态:

1)运行态(Resumedstate

   此时Activity程序显示在屏幕前台,并且具有焦点,可以与用户的操作进行交互,如向用户提供信息、捕获用户单击按钮的事件并做处理。

2)暂停态(PausedState

此时Activity程序失去了焦点,并被其他处于运行态的otherActivity取代在屏幕显示,但otherActivity程序并没有覆盖整个屏幕或者具有半透明的效果—此状态即为暂停态。处于暂停态的Activity仍然对用户可见,并且是完全存活的(此时Activity对象存留在内存里,保留着所有状态与成员信息并保持与窗口管理器的连接)。如果系统处于内存不足的情况下,会杀死这个Activity

3)停止态(StoppedState

Activity完全被另一个otherActivity覆盖时(此时otherActivity显示在屏幕前台),则处于停止态。处于停滞态的Activity依然是存活的(此时Activity对象依然存留在内存里,保留着所有的状态和与成员信息,但没有与窗口管理器保持连接),而且它对用户是不可见的,如果其他地方需要内存,系统会销毁这个Activity



   处于暂停态(PausedState)或者停止态(Stopped State)Activity,系统可以通过调用finish()方法或者直接终止它的进程来销毁此Activity(从内存中清楚此Activity对象)。被finish()或者销毁的Activity再重新打开时,是需要再次初始化此Activity的。


22

当一个Activity从一种状态转到另一种状态时,会通过调用回调方法来通知这种变化。这些回调方法都是可以重写的,你可以根据程序的的需要来选择重写对应的回调方法。以下列出了Activity生命周期里的基本回调方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
public  class  ExampleActivity  extends  Activity {
     @Override
     public  void  onCreate(Bundle savedInstanceState) {
         super .onCreate(savedInstanceState);
         // The activity is being created.
     }
     @Override
     protected  void  onStart() {
         super .onStart();
         // The activity is about to become visible.
     }
     @Override
     protected  void  onResume() {
         super .onResume();
         // The activity has become visible (it is now "resumed").
     }
     @Override
     protected  void  onPause() {
         super .onPause();
         // Another activity is taking focus (this activity is about to be "paused").
     }
     @Override
     protected  void  onStop() {
         super .onStop();
         // The activity is no longer visible (it is now "stopped")
     }
     @Override
     protected  void  onDestroy() {
         super .onDestroy();
         // The activity is about to be destroyed.
     }
}

   笔记:在方法体里,必须先调用父类对应的实现方法super.Xxx(),再执行其他的操作(如上面代码所示)。为了习惯,下面也提供一些代码来测试一些这些方法的使用,在博客的最后面。


   总的来说,这些回调方法定义了Activity整个生命周期。在生命周期里通过重写这些回调方法,,你可以监控以下下三个嵌套的方法循环。


完整存活的时间:

Activity的完整存活的时间是自第一次调用onCreate()开始,直至调用onDestroy()为止。ActivityonCreate()中设置所有“全局”状态以完成初始化,而在onDestroy()中释放所有系统资源。例如,如果Activity有一个线程在后台运行从网络下载数据,它会在onCreate()创建线程,而在 onDestroy()销毁线程。


可见状态的时间:

Activity的可见状态是自onStart()调用开始直到相应的onStop()调用结束。在此期间,用户可以在屏幕上看到Activity,尽管它也许并不是位于前台或者也不与用户进行交互。在这两个方法之间,我们可以保留用来向用户显示这个Activity所需的资源。例如,当用户不再看见我们显示的内容时,我们可以在onStart()中注册一个BroadcastReceiver来监控会影响UI的变化,而在onStop()中来注消。onStart()  onStop() 方法可以随着应用程序是否为用户可见而被多次调用。


显示在前台的时间:

  Activity的前台显示是自onResume()调用起,至相应的onPause()调用为止。在此期间,Activity位于前台最上面并与用户进行交互。Activity会经常在暂停和恢复之间进行状态转换——例如当设备转入休眠状态或者有新的Activity启动时,将调用onPause() 方法。当Activity获得结果或者接收到新的Intent时会调用onResume() 方法。


2.3

下图显示了这三个循环之间的状态转换(其中写在长方形里的是你可以用来重写并实现对应操作的方法)。










































同样的,以下面的表格来描述生命周期里的回调方法,并包含了更加详细的信息。

方法

描述

是否可以终止

下一个方法

onCreate()

Activity程序启动之后会首先调用此方法。在这个方法体里,你需要完成所有的基础配置——创建视图,连接数据库并将数据绑定到list列表中,等等。这个方法会传递一个保存了此Activity上一状态信息的Bundle对象。紧随其后的方法总是onStart().

不可以

onStart()


onRestart()

处于停止态的Activity调用此方法,可以让此Activity重新显示在前台。

紧随其后的方法总是onStart()

不可以

onStart()

onStart()

在此Activity可见(显示在前台)之前调用。

如果接着是显示在前台,紧随其后的方法是onResume()如果接下来此Activity被隐藏了,则紧随其后的方法是onStop()

不可以

onResume()

onStop()


onResume()

在与用户进行交互之前调用此方法,这一时刻Activity位于activity栈的栈顶,在等待用户的操作(输入数据或点击按钮等)。紧随其后的方法是onPause().

不可以

onPause()

onPause()

当启动其他activity时调用此方法。在这个方法体里,通常用于提交未保存的数据、停止动画/视频和处理其他占用CPU资源的程序,等等。同时在这个方法体里处理的都是一些迅速快捷的操作,因为下一个activity会在onPause()方法执行完之后才可以在前台显示

如果此Activity重新回到前台显示,则紧随其后的方法是onResume();如果此Activity变得不可见了,则紧随其后的方法是onStop()

可以

onResume()

onStop()

onStop()

Activity不可见时调用此方法。这个方法的调用时刻是在Activity需要销毁或者被其他otherActivity取代且覆盖此Activity在前台显示时调用。

如果此Activity重新显示在前台,紧随其后的方法是onRestart();如果此Activity需要被销毁,紧随其后的方法是onDestroy()

可以

onRestart()

onDestroy()

onDestroy()

Activity被销毁时调用此方法。这是Activity生命周期里最后调用的一个方法。这个方法的调用可以发生在activity调用了finish()方法之后,或者是系统为了节省空间而销毁了此Activity的实例。你可以使用isFinishing()方法来区分这两种情况。

可以

——


   “是否可以终止”是指系统是否可以在此方法执行完后直接销毁该Activity的实例(没有再去执行此Activity内的其他代码)。如上表所示,onPause(),onStop(),onDestroy()三个方法是可以终止的。同时从状态图(上图)中可以知道onPause()方法是这三个方法中第一个调用的,自一个Activity创建开始,直到此Activity终止或销毁,onPause()是最后一个保证会被调用的方法(如在突发情况下系统回收内存,onStop()onDestroy()就不会被调用)。因此,你应该在onPause()方法里保存一些关键的数据(如用户编辑的内容),所谓“关键“就是让你有选择地去保存一些重要的数据,因为onPause()方法执行时间过长,会延迟下一状态的切换,进而影响了用户的体验。

   附:在上表注明不可以被终止的方法也可能会被系统终止,不过这一情况只会在一些极端的情况下发生。


三、保存Activity的状态信息

   在前文提到过,处于暂停态的和停止态的Activity,其对应的状态的状态与成员信息依然保留在内存里。那么这些信息又是如何保存的??我们又应该如何去利用这些信息??

   在暂停状态下的activity,因其activity信息完整保存在内存里且保持与窗口管理器的连接,所以可以直接调用onRestart()方法还原activity

用户经常会使用返回按钮返回上一个界面(Activity),用户当然是希望上一个界面(Activity)和他原来看到或编辑的一样,在这种情况下你就需要使用之前已经保存好的状态信息和成员变量来还原上一个Activity。若要保存一个Activity的状态信息和成员变量,则需要实现回调方法onSaveInstanceState()

   onSaveInstanceState()会在执行onStoped()方法之前调用,这个方法有一个参数Bundle,可以以“名称-值”的形式保存activity的信息(如使用putString(),putInt()方法)。接着在需要还原activity时,系统会调用onCreat()或者OnRestoreInstanceState()这两个方法都传入一个以保存了activity信息的Bundle对象,通过提取Bundle对象的信息来恢复activity。如果没有信息需要保存到Bundle对象,那传递给这两个方法的将是空的Bundle对象(刚开始初始化一个activity时其实就是这种情况)。如下图所示:

   其实,即使你没有实现回调方法onSaveInstanceState()系统也会执行默认的onSaveInstanceState()值得注意的是,系统会为每个View组件执行相对应的onSaveInstanceState(),这可以使每一个组件保存自己相对应的信息。在Android里,几乎所有的控件都实现了这个方法,因此在界面产生的可见变化都会自动保存下来,也就可以还原activity。举个例子:在EditText输入的内容或者CheckBox的选择,都会自动保存下来。而你所需要做的就是为需要保存信息的控件提供一个id(在XML文件里的属性android:id,如果你没有为控件提供id,那系统是不会自动保存这些信息的。

下面给出一些例子参考一下onSaveInstanceState()OnRestoreInstanceState()方法的使用:


1
2
3
4
5
6
7
8
9
10
11
12
13
14
@Override
     protected  void  OnSaveInstanceState(Bundle outState)
     {
         outState.PutString( "myString" "HelloXamarin.Android OnSaveInstanceState" );
         outState.PutBoolean( "myBool" true );
         base.OnSaveInstanceState(outState);
     }
     @Override
     protected  void  OnRestoreInstanceState(Bundle savedState)
     {
         base.OnRestoreSaveInstanceState(savedState);
         var myString =savedState.GetString(amyStringa);
         var myBool =GetBoolean(amyBoola);
     }

   附:如果需要强制控件不保存对应的信息,可以在布局文件设置android:saveEnabled = false”,或者使用控件对象的setSaveEnabled()方法。


   尽管系统默认执行onSaveInstanceState()保存对应控件的信息,有时候你需要实现这个方法去保存一些额外的变量。例如:你需要去保存一些在这个activity生命周期里会改变的变量(指控件信息之外的变量),这些会改变的变量系统是默认不保存的。

   需要注意的是:onSaveInstanceState()方法不保证一定会被调用,所以在这个方法里你只应该保存一些临时变量(如UI的状态),而不要去保存一些需要持久化的数据。相反,你应该在onPaused()方法里保存需要持久化的数据(例如保存到数据库里的数据)。

tips

     Android系统上Back按钮和Home按钮的区别,尽管他们都可以导航到另外一个otherActivity(可以是其他程序的),可他们的作用原理是不一样的。在界面(Activity)上点击Back按钮,系统会认为这个Activity已完成其对应的实现逻辑,则调用对应的方法销毁此Activity;可当点击Home按钮时,系统会认为这个Activity还没有完成对应的逻辑,则系统并不会销毁这个Activity,而是让其处于停止态(Stopped State.



四、协调各个Activity

   当ActivityA启动ActivityB时,这两个Activity都需要进行状态的切换。当ActivityB创建的时候,ActivityA会切换到暂停态或者停止态(当ActivityA依然可见是切换到暂停态,不可见则切换到停止态)。假设这两个Activity共享某些存储在磁盘的数据,这样很有必要去知道,在ActivityB创建完成之前,ActivityA都还没有切换到停止态(StopppedState)

   当两个Activity处于源于同一个App,又是一个启动另外一个Activity的时候,其生命周期的回调方法是已经定义好的了。一下是这两个Activity状态切换个回调方法的调用顺序。

  1.执行ActivityAonPaused()方法

  2.依次执行ActivityBonCreate(),onStart(),onResume()方法(此时ActivityB显示在前台,获得焦点)。

  3.然后,如果ActivityA变得不可见,则执行ActivityAonStopped()方法。

   根据这些方法调用顺序,可以知道:如果需要在ActivityA保存数据到数据库,接着让ActivityB读取,那么你应该onPaused()方法里执行持久化操作,而不是在onStopped()方法里。



附录:activityLifecycle的代码和运行效果图。

输出:

输出(注意其调用的顺序):

输出:


ActivityA的代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
public  class  ActivityA  extends  Activity {
     @Override
     public  void  onCreate(Bundle savedInstanceState) {
         super .onCreate(savedInstanceState);
         setContentView(R.layout.activity_a);
         System.out.println( "ActivityA-->onCreate()" );
     }
     @Override
     protected  void  onStart() {
         super .onStart();
         System.out.println( "ActivityA-->onStart()" );
     }
     @Override
     protected  void  onRestart() {
         super .onRestart();
         System.out.println( "ActivityA-->onRestart()" );
     }
     @Override
     protected  void  onResume() {
         super .onResume();
         System.out.println( "ActivityA-->onResume()" );
     }
     @Override
     protected  void  onPause() {
         super .onPause();
         System.out.println( "ActivityA-->onPause()" );
     }
     @Override
     protected  void  onStop() {
         super .onStop();
         System.out.println( "ActivityA-->onStop()" );
     }
     @Override
     protected  void  onDestroy() {
         super .onDestroy();
         System.out.println( "ActivityA-->onDestroy()" );
     }
     public  void  startDialog(View v) {
         Intent intent =  new  Intent(ActivityA. this , DialogActivity. class );
         startActivity(intent);
     }
     public  void  startActivityB(View v) {
         Intent intent =  new  Intent(ActivityA. this , ActivityB. class );
         startActivity(intent);
     }
                                                                                                                                              
     public  void  finishActivityA(View v) {
         ActivityA. this .finish();
     }
}
Action


DialogActivity代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
public  class  DialogActivity  extends  Activity {
     @Override
     protected  void  onCreate(Bundle savedInstanceState) {
         super .onCreate(savedInstanceState);
         requestWindowFeature(Window.FEATURE_NO_TITLE);
         setContentView(R.layout.activity_dialog);
         System.out.println( "DialogActivity-->onStart()" );
     }
                                                                                                   
     @Override
     protected  void  onStart() {
         super .onStart();
         System.out.println( "DialogActivity-->onStart()" );
     }
     @Override
     protected  void  onRestart() {
         super .onRestart();
         System.out.println( "DialogActivity-->onRestart()" );
     }
     @Override
     protected  void  onResume() {
         super .onResume();
         System.out.println( "DialogActivity-->onResume()" );
     }
     @Override
     protected  void  onPause() {
         super .onPause();
         System.out.println( "DialogActivity-->onPause()" );
     }
     @Override
     protected  void  onStop() {
         super .onStop();
         System.out.println( "DialogActivity-->onStop()" );
     }
     @Override
     protected  void  onDestroy() {
         super .onDestroy();
         System.out.println( "DialogActivity-->onDestroy()" );
     }
                                                                                                   
     public  void  finishDialog(View v) {
         DialogActivity. this .finish();
     }
                                                                                                   
}

其他代码类似,就不一一张贴了。



  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值