Android Activity生命周期

一、概念

  1. 每个Activity实例都有其生命周期。在其生命周期内,activity在运行、暂停、停止三种可能的状态间进行转换。每次状态发生转换时,都有一个Activity方法将状态改变的消息通知给activity。

  

       (此图来源于Android书籍权威指南)

  (1). onCreate:表示Activit正在被创建,与其相对应的是onDestory。

   (2). onRestart:表示Activity正在重新启动,一般情况下,Activity从不可见状态到可见状态。

  (3). onStart:表示Activity正在被启动,即将开始,此时,Activity已经可见。与其相对应的是onStop。

  (4). onResume:表示Activity已经可见,并且出现在前台并开始活动。与其相对应的是onPause。

  (5). onPause:表示Activity正在被停止,正常情况下,紧接着onStop被回调。

  (6). onStop:表示Activity即将停止,可以做一些稍微回收工作,但是不能太耗时。

  (7). onDestory:表示Activity即将销毁,这是Activity生命周期最后一个回调,在这里可以做一些回收工作和资源释放。

  PS:Activity整个生命周期中onCreate和onDestory是配对,分别代表时,Activity的创建和销毁,在整个周期中只能调用一次;从Activity是否可见来说,onStart和onStop是配对的,随着用户的操作或者设备屏幕的点亮和熄灭,这两个方法被多次调用,表示Activity的可见和不可见状态;从Activity是在前台来说,onResume和onPause是配对的,随着用户的操作和设备屏幕的点亮和熄灭,这两个方法被多次调用,表示Activity的在前台和在后台的状态。

在Activity类中,生命周期的方法:

 1 public class ActivityDemo extends Activity
 2         {
 3             @Override    // 表示Activity正在被创建
 4             public void onCreate(Bundel savedInstanceState){}
 5 
 6             @Override    // Activity从不可见到可见状态
 7             public void onRestart(){}
 8             
 9             @Override   // 表示Activity被启动,已经可见
10             public void onStart(){}
11 
12             @Override    // 表示Activity已经可见了,并且出现到前台开始活动
13             public void onResume(){}
14 
15             @Override    // 表示Activity正在被停止,正常情况下,紧接着onStop()被调用
16             public void onPuase(){}
17 
18             @Override    // 表示Activity即将停止,可以做一些稍微重量级的回收工作,但不能太耗时
19             public void onStop(){}
20 
21             @Override    // 表示Activity即将被销毁,这是Activity生命周期中,最后一个回调,可以做一些回收工作和最终的资源释放
22             public void onDestroy(){}
23         }

PS:在覆盖实现Activity生命周期方法时,在实现中,要先行调用超类(基类)的生命周期方法。Activity生命周期方法,不要自己调用,这个调用由android系统自己进行。Activity直接理解就是一个View从创建到显示,再到消失销毁的整个过程,在这个过程中,Activity状态在不停的转换。

  •  onDestroy()方法在Activity销毁前调用,用于销毁Activity中的对象。
  • onFinish()方法是主动结束Activity的生命周期,在其中会去调用onDestroy()方法。

2. Activity切换时,生命周期方法执行顺序:

  (1) 在一个Activity进入新建一个Activity时,生命周期方法执行:

  1. 第一个Activity的onPause();
  2. 第二个Activity的onCreate();
  3. 第二个Activity的onStart();
  4. 第二个Activity的onResume();
  5. 第一个Activity的onStop();

  (2) 在新建的Activity返回到前一个Activity时,生命周期方法执行:

  1. 第二个Activity的onPause();
  2. 第一个Activity的onRestart();
  3. 第一个Activity的onStart();
  4. 第一个Activity的onResume();
  5. 第二个Activity的onStop();
  6. 第二个Activity的onDestroy();

  (3) Activity进入后台,再进入前台:

  1. onPause();
  2. onStop();
  3. onRestart();
  4. onStart();
  5. onResume();

  (4) ActivityA、ActivityB、ActivityC,其中ActivityB launchMode=singleTask,并A、B、C依次入栈后,ActivityC通过startActivity(...)启动ActivityB时生命周期:

  1. ActivityC onPause();

  2. ActivityB onRestart();

  3. ActivityB onStart();

  4. ActivityB onResume();

  5. ActivityC onStop();

  6. ActivityC onDestroy();

3. Activity实例在任务栈重用时,生命周期方法执行顺序:

  1. onPause();
  2. onResume();

PS: 配置Activity的lauchMode=singleTop。

二、Activity销毁原因

  • android系统回收内存时,会将暂停或停止的Acitvity销毁。但不会销毁正在运行的Activity。
  • 用户离开当前Activity管理的用户界面,Activity也会被销毁。

PS:Activity在暂停、停止及销毁前,会先调用onSaveInstanceState(...)方法。

三、多个Activity切换

  通过startActivity(...)和startActivityForResult(...)进入另一个指定的Activity,Activity在finish()后,调用onDestroy()方法,销毁Activity对象。通过setResult(...)方法,在显示栈中顶层Activity时,标记从哪个Activity返回的。并且,传递返回的数据结构。

  MainActivity.java:

 1 public class MainActivity extends Activity
 2 {
 3     @Override
 4     public void onCreate(Bundle savedInstanceState)
 5     {
 6         super.onCreate(savedInstanceState);
 7         setContentView(R.layout.activity_main);
 8 
 9         setupUI();
10     }
11 
12     public void setupUI()
13     {
14         LinearLayout navigation = new LinearLayout(this);
15         navigation.setOrientation(LinearLayout.VERTICAL);
16         TextView titleView = new TextView(this);
17         titleView.setText("Main Activity");
18         LinearLayout.LayoutParams layoutParam = new LinearLayout.LayoutParams(LinearLayout
19                 .LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT);
20         layoutParam.gravity = Gravity.CENTER;
21         navigation.addView(titleView, layoutParam);
22 
23         Button pushView = new Button(this);
24         pushView.setText("进入下一界面");
25         pushView.setOnClickListener(new View.OnClickListener()
26         {
27             @Override
28             public void onClick(View v)
29             {
30                 Toast.makeText(MainActivity.this, "进入下一个界面", Toast.LENGTH_SHORT).show();
31 
32                 // intent
33                 Intent intent = new Intent();
34                 intent.setClass(MainActivity.this, SecondActivity.class);
35                 intent.putExtra("title", "第二个界面");
36                 startActivityForResult(intent, 11);
37             }
38         });
39         navigation.addView(pushView, layoutParam);
40         addContentView(navigation, layoutParam);
41     }
42 
43     @Override
44     protected void onActivityResult(int requestCode, int resultCode, Intent data)
45     {
46         Toast.makeText(this, "onActivityResult", Toast.LENGTH_SHORT).show();
47         Intent intent = getIntent();
48         Toast.makeText(this, "return result finish", Toast.LENGTH_SHORT).show();
49     }
50 }

  SecondActivity.java:

 1 public class SecondActivity extends Activity
 2 {
 3     @Override
 4     public void onCreate(Bundle savedInstanceState)
 5     {
 6         super.onCreate(savedInstanceState);
 7         setContentView(R.layout.activity_second);
 8 
 9         setupNavigation();
10     }
11 
12     public void setupNavigation()
13     {
14         LinearLayout navigation = new LinearLayout(this);
15         navigation.setOrientation(LinearLayout.HORIZONTAL);
16 
17         String title = getIntent().getSerializableExtra("title").toString();
18         ViewGroup.LayoutParams childParams = new ViewGroup.LayoutParams(LinearLayout
19                 .LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT);
20 
21         Button back = new Button(this);
22         back.setText("返回");
23         back.setOnClickListener(new BackLisenter());
24         navigation.addView(back, childParams);
25 
26         TextView titleView = new TextView(this);
27         titleView.setText(title);
28         navigation.addView(titleView, childParams);
29 
30         LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(LinearLayout
31                 .LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT);
32         layoutParams.gravity = Gravity.CENTER;
33         addContentView(navigation, layoutParams);
34         Toast.makeText(this, title, Toast.LENGTH_SHORT).show();
35 
36     }
37 
38     private class BackLisenter implements View.OnClickListener
39     {
40         @Override
41         public void onClick(View v)
42         {
43             // 设置返回数据结构
44             HashMap<String, String> maps = new HashMap<>();
45             maps.put("id", "001");
46             maps.put("name", "naray");
47             Bundle bundle = new Bundle();
48             bundle.putSerializable("items", maps);
49             Intent intent = new Intent();
50             intent.putExtras(bundle);
51             // 指定返回到栈中顶层的Activity,标记从哪个Activity返回,并传递的数据结构
52             setResult(9, intent);
53             // 结构Activity生命周期
54             finish();
55         }
56     }
57 }

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

  4.1 资源相关的系统配置发生改变导致Activity被销毁并重新创建

  比如,当前Activity保处于竖屏状态,如果实然旋转屏幕,由于系统配置发生了改变,在默认情况下,Activity就会被销毁并且重新创建。当然,这一情况也是可以被阻止的,不让系统重新创建Activity。

  在默认情况下,Activity不做特殊处理,当系统配置发生改变后,Activity就会被销毁,其中的onPause、onStop、onDestory方法会被调用,同时,由于Activity是被异常终止的,系统会调用onSaveInstanceState方法保存当前Activity的场景状态。这个方法在onStop方法调用之前被调用,与onPause方法没有既定的时序关系,即可以在onPause之前,也可以在onPause之后被调用。

  PS:onSaveInstanceState方法只会在Activity异常情况下被终止时被系统调用,在正常情况下Activity的终止是不会被系统调用的。

  在Activity异常终止销毁后,重新创建系统会调用onRestoreInstanceState方法,并且会将Activity被异常终止销毁时,调用onSaveInstanceState方法时,存储的Bundle对象作为参数传递给onRestoreInstanceState和onCreate方法。因此,可以通过onRestoreInstanceState和onCreate方法判断Activity是否是被重新创建的,如果被重新创建了,就取出存储的数据并且恢复之,从时序上来说,onRestoreInstanceState调用时机是在onStart方法调用之后,系统会调用onRestoreInstanceState方法。

  同时,要知道在onSaveInstanceState和onRestoreInstanceState方法,系统默认做了一些事情用于帮忙恢复Activity在创建后,恢复Activity场景状态。 

  Activity异常情况下的销毁和重建(示例为屏幕旋转的情况): 

  

  4.1.1 屏幕旋转时,禁止重建Activity

  通过设置configChanges配置禁止在异常情况下,重建Activity。

1 <activity
2         android:name=".Activity.MainActivity"
3         android:configChanges="orientation|screenSize|keyboardHidden">
4 </activity>

  然后,重写onConfigurationChanged方法:

@Override
public void onConfigurationChanged(Configuration newConfig)
{
    super.onConfigurationChanged(newConfig);
    Log.d(TAG, "onConfigurationChanged");
}

  4.2 资源内存不足导致低优先级的Activity被销毁

  这种情况下的数据存储和数据恢复与4.1情况完全一致。在这里我们描述一下Activity的优先级情况。Activity的优先级按照从高到低可以分为三种情况:

  (1). 前台Activity,正在与用户交互的Activity,优先级最高。

  (2). 可见但非前台Activity,比如Activity中弹出一个对话框,导致Activity可见,但是Activity位于后台,无法与用户直接交互。

  (3). 后台Activity,已经被暂停Activity,即执行了onStop方法,优先级最低。

原文地址:https://www.cnblogs.com/naray/p/5276241.html