Android中Activity生命周期浅析

来源:互联网 发布:网络翻译招聘 编辑:程序博客网 时间:2024/06/04 23:27

编写不易,如有转载,请声明出处: 梦回河口:http://blog.csdn.net/zxc514257857/article/details/76686607

Activity形态

  Activity是由Activity栈进行管理,当来到一个新的Activity后,此Activity将被加入到Activity栈顶,之前的Activity位于此Activity底部。Activity最大的特点就是拥有多种形态,在多种形态间进行切换,控制自己的生命周期

  • Active/Running形态

  此时,Activity处于Activity栈的栈顶,可见且可交互

  • Paused形态

  当Activity失去焦点,被一个新的非全屏的Activity或者透明的Activity放置在栈顶时(此时原Activity失去栈顶位置),Activity就转化为了paused形态。不可交互但所有状态信息,变量都还保持着,只有在系统内存极低的情况下才会被系统回收

  • Stopped形态

  当Activity失去焦点,且被一个新的全屏不透明的Activity覆盖,Activity就进入stopped形态。此时,Activity不再可见

  • Killed形态

  当Activity被系统回收掉或Activity从来没有创建过,Activity就处于Killed形态

Activity生命周期

这里写图片描述

  图中详细给出了Activity整个生命周期的过程,以及在不同的状态期间相应的回调方法
  从图中可以看出:

  • 一个最简单的完整的Activity生命周期会按照如下顺序回调:onCreate() —> onStart() —> onResume() —> onPause() —> onStop() —> onDestroy() 。这称之为entire lifetime。在系统调用onCreate()之后,就会马上调用onStart(),然后继续调用onResume()完成启动,最后系统会调用onDestory()来结束一个Activity的生命周期让它回到Killed形态

  • 由onStart() —> onResume() —> onPause(),一直到onStop()方法调用之前,这段生命周期内Activity都是被用户可见的。这称之为visible lifetime

  • 由onResume()一直到onPause()方法调用之前,这段生命周期内Activity都是可以响应用户交互的(即前台的或者是可以获取焦点的)。这称之为foreground lifetime

  由此我们可以知道:

  • invisible lifetime由onCreate() 、onStop() —> onDestory()阶段组成。background lifetime由 (除onResume()到onPause()方法调用之前这一阶段) 组成

  • 一个应用程序在进程不被系统清除的情况下由后台恢复到前台,有两种方式: onPause() —> onResume() ,重新获取焦点;onStop() —> onRestart() —> onStart() —> onResume()

  • Activity生命周期有三个状态是稳定的,其他状态都是过渡状态,很快就会结束。Resumed状态 可见,可交互(最常见状态);Raused状态 不可交互,可见(失去栈顶);Stopped状态 不可交互,不可见(后台状态)

  • onCreate()中一般需要完成:创建基本UI元素;onResume() 中一般需要完成:重新初始化在onPause()中释放的资源;onpause()和onStop()中一般需要完成:清除Activity的资源,避免浪费,如Camera,sensor,Receiver等;onDestory()中一般需要完成:清除开启的线程

onSaveInstanceState()

  • 来源

  如果你的应用长时间处于Stopped状态,而且此时系统需要更多内存或者内存极为紧张时,系统就会回收你的Activity,而此时系统为了补偿你,会将Activity状态通过onSaveInstanceState()方法保存到Bundle对象中,当然你也可以增加额外的键值对存入Bundle对象以保存这些状态。当你需要重新创建这些Activity的时候,保存的Bundle对象就会传递到Activity的onRestoreInstanceState()方法与onCreate()方法中,这也就是onCreate()方法中参数——-Bundle savedInstanceState的来源(这里持怀疑态度,因为当我在onSaveInstanceState()方法中存入Bundle savedInstanceState参数后,只有在横竖屏切换时才走onCreate()和onRestoreInstanceState()方法取出数据,其他情况都无法取出)

  • 调用时机

   onSaveInstanceState()并不是每次当Acitivity离开前台时都会调用,如果用户使用finish()方法主动去结束一个Activity则不会调用。因为在这种情况下,用户的行为决定了不需要保存Activity的状态。通常onSaveInstanceState()只适合用于保存一些临时性的状态,而onPause()适合用于数据的持久化保存。Android系统已经默认实现了控件的状态缓存,以此来减少开发者需要实现的缓存逻辑

  • 源码分析

   onSaveInstanceState ()是在函数里面保存一些View有用的数据到一个Parcelable对象并返回。在Activity的onSaveInstanceState(Bundle outState)中调用View的onSaveInstanceState (),返回Parcelable对象,接着用Bundle的putParcelable方法保存在Bundle savedInstanceState中。当系统调用Activity的的onRestoreInstanceState(Bundle savedInstanceState)时,通过Bundle的getParcelable方法得到Parcelable对象,然后把该Parcelable对象传给View的onRestoreInstanceState (Parcelable state)。在的View的onRestoreInstanceState中从Parcelable读取保存的数据以便View使用

Activity中onCreate()源码实现
这里写图片描述

Activity中onSaveInstanceState(Bundle outState)源码实现
这里写图片描述

Activity中onRestoreInstanceState(Bundle savedInstanceState)源码实现
这里写图片描述

   如果我们没有重写onSaveInstanceState()方法,此方法的默认实现会自动保存activity中的某些状态数据, 比如activity中各种UI控件的状态。android应用框架中定义的几乎所有UI控件都恰当的实现了onSaveInstanceState()方法,因此当activity被摧毁和重建时,这些UI控件会自动保存和恢复状态数据。比如EditText控件会自动保存和恢复输入的数据,而CheckBox控件会自动保存和恢复选中状态。开发者只需要为这些控件指定一个唯一的ID(通过设置android:id属性即可), 剩余的事情就可以自动完成了。如果没有为控件指定ID,则这个控件就不会进行自动的数据保存和恢复操作。由上所述, 如果我们需要重写onSaveInstanceState()方法,一般会在第一行代码中调用该方法的默认实现:super.onSaveInstanceState(outState)

  • 重写时机

   如果需要保存额外的数据时, 就需要重写onSaveInstanceState()方法。大家需要注意的是:由于onSaveInstanceState()方法方法不一定会被调用, 因此不适合在该方法中保存持久化数据, 例如向数据库中插入记录等,onSaveInstanceState()方法只适合保存瞬态数据,比如UI控件的状态,成员变量的值等,持久化数据应该当用户离开当前的 activity时,在 onPause() 中保存(比如将数据保存到数据库或文件中)。若是永久性值,则在onPause()中保存;若数量较大,则另开线程吧,别阻塞UI线程

代码验证

import android.content.Intent;import android.os.Bundle;import android.support.v7.app.AppCompatActivity;import android.util.Log;public class MainActivity extends AppCompatActivity {    private static final String TAG = "MainActivity";    // 何时会取出Bundle中的数据?    // 后台到前台/锁屏/多界面应用切换/界面跳转 不会取   设置了"开发者选项"--->"不保留活动"就会取了    // 旋转屏幕会取      @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        Log.i(TAG, "onCreate-->" + "创建!");        if(savedInstanceState != null){            String string = savedInstanceState.getString("Activity");            Log.i(TAG , "onCreate-->从Bundle中取出数据:" + string);        }    }    @Override    protected void onStart() {        super.onStart();        Log.i(TAG, "onStart-->" + "可见!");    }    @Override    protected void onResume() {        super.onResume();        Log.i(TAG, "onResume-->" + "获取焦点!");    }    @Override    protected void onPause() {        super.onPause();        Log.i(TAG, "onPause-->" + "失去焦点!");    }    @Override    protected void onStop() {        super.onStop();        Log.i(TAG, "onStop-->" + "不可见!");        // int a = 5/0;    }    @Override    protected void onDestroy() {        super.onDestroy();        Log.i(TAG, "onDestroy-->" + "销毁!");    }    @Override    protected void onRestart() {        super.onRestart();        Log.i(TAG, "onRestart-->" + "重新恢复可见!");    }    @Override    public void onBackPressed() {        Intent intent = new Intent(MainActivity.this , SecondActivity.class);        startActivity(intent);    }    // 何时会调用此onSaveInstanceState方法?    // 后台到前台/锁屏/旋转屏幕/多界面应用切换/界面跳转 会调用    // 按back键销毁  不会调用    @Override    public void onSaveInstanceState(Bundle outState) {        super.onSaveInstanceState(outState);        String string = "Bundle中存储的数据!";        outState.putString("Activity" , string);        Log.i(TAG, "onSaveInstanceState-->" + "保存数据在Bundle中!");    }    @Override    public void onRestoreInstanceState(Bundle savedInstanceState) {        super.onRestoreInstanceState(savedInstanceState);        String string = savedInstanceState.getString("Activity");        Log.i(TAG , "onRestoreInstanceState-->从Bundle中取出数据:" + string);    }}----------------------------------------------------------------------------------------import android.content.Intent;import android.support.v7.app.AppCompatActivity;import android.os.Bundle;import android.util.Log;public class SecondActivity extends AppCompatActivity{    private static final String TAG = "SecondActivity";    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_sec);        Log.i(TAG, "onCreate-->" + "创建!");    }    @Override    protected void onStart() {        super.onStart();        Log.i(TAG, "onStart-->" + "可见!");    }    @Override    protected void onResume() {        super.onResume();        Log.i(TAG, "onResume-->" + "获取焦点!");    }    @Override    protected void onPause() {        super.onPause();        Log.i(TAG, "onPause-->" + "失去焦点!");    }    @Override    protected void onStop() {        super.onStop();        Log.i(TAG, "onStop-->" + "不可见!");    }    @Override    protected void onDestroy() {        super.onDestroy();        Log.i(TAG, "onDestroy-->" + "销毁!");    }    @Override    public void onBackPressed() {        Intent intent = new Intent(SecondActivity.this , MainActivity.class);        startActivity(intent);        finish();    }}
  • 启动应用,进入MainActivity
    这里写图片描述

  • MainActivity—>SecondActivity:
    这里写图片描述

  • SecondActivity—>MainActivity:
    这里写图片描述

   以上验证了一个Activity的完整生命周期;两个Activity之间的跳转生命周期回调;Activity跳转时finish()的作用;

  • 后台到前台/锁屏/多界面应用切换:
    这里写图片描述

   以上验证了后台到前台/锁屏/多界面应用切换/界面跳转会调用onSaveInstanceState(Bundle outState)方法,但不会因为内存不足而取出保存的数据

  • 横竖屏切换:
    这里写图片描述

   以上验证了横竖屏切换可以保存也可以取出Bundle中的数据

  • 设置了”开发者选项”—>”不保留活动”:
    这里写图片描述
       系统对不保留活动的描述就是:用户离开后即销毁每个活动,即只要应用不可见系统就会自动调用onDestory()方法,以上验证了,在设置了不保留活动的情况下,系统可以保存也可以取出Bundle中的数据

参考资料:http://www.cnblogs.com/lwbqqyumidi/p/3769113.html
     http://blog.csdn.net/javazejian/article/details/51932562


———-因本人才疏学浅,如博客或Demo中有错误的地方请大家随意指出,与大家一起讨论,共同进步,谢谢!———-

原创粉丝点击