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

这里所说的异常主要是分为以下这在两种情况下的异常:

情况1、资源相关的系统配置发生改变Activity被杀死并被杀死重新创建Activity

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

情况一具体:

那最简单的加载图片资源文件的机制来说,我们将图片放进drawable目录下,开发时为了兼容不同的设备,可能放的不只放在这一个目录中,还有drawable-mdpi,

drawable-hdpi这些目录中,当程序启动的时候会根据设备的情况进行加载合适的图片资源,比如手机的横屏向竖屏进行切换的时候,在切换的过程中Activity就会被销毁

并且进行重建。这个时候会出现一个问题,就是你在竖屏上显示的内容,比如EditText内输入的文字,就会在重构的时候被杀死,这时候你在横屏上就会呈现的EditText

在竖屏上的输入的文字,便统统清空,这个问题在以前的写程序的时候也遇到过,没当时事,前天在慕课上学习一个五子棋的游戏的时候,在最后老师进行提到这个问题,

并且对代码进行了处理。这样的话在你无意切换成宽屏的时候,棋盘不会进行清空。

如果不做这种处理当系统配置进行发生改变的时候其生命周期就会变成这样:盗个图

从竖屏到横屏这一个操作中,关键的生命周期经历这几个过程Log

 I/com.example.hejingzhou.activityleft.MainActivity: onPause()
 I/com.example.hejingzhou.activityleft.MainActivity: onSaveInstanceState()被调用
 I/com.example.hejingzhou.activityleft.MainActivity: onStop()
 I/com.example.hejingzhou.activityleft.MainActivity: onDestroy()
 I/com.example.hejingzhou.activityleft.MainActivity: onCreate()
 I/com.example.hejingzhou.activityleft.MainActivity: onRestoreInstanceState()被调用

这里添加一个刚刚知道的一个知识点,在Activity生命周期中,onStart  onStop 与 onResume onPause的不同在于前者主要是从Activity 是否可见的角度进行回调,

而后者是从Activity是否位于前台这个角度来回调的。在onPause中不能进行重量级的操作,也就是耗时复杂的操作,因为必须onPause执行完后才对新的Activity

onResume。

我们就举EditText输入的问题进行举例。

@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Log.i(TAG,"onCreate()");
        editText = (EditText) findViewById(R.id.editView);
    }

    @Override
    protected void onSaveInstanceState(Bundle outState) {
        Log.i(TAG, "onSaveInstanceState()被调用");
        strData = editText.getText().toString();
        outState.putString("editData", strData);
        super.onSaveInstanceState(outState);
    }

    @Override
    protected void onRestoreInstanceState(Bundle savedInstanceState) {
        Log.i(TAG, "onRestoreInstanceState()被调用");
        super.onRestoreInstanceState(savedInstanceState);
        String string = savedInstanceState.getString("editData");
        Log.i(TAG, string);
        //editText.setText(string);
    }

这样就可以进行对String类型进行保存,这样的话在切换成横屏的时候EditText输入的数据还是进行了保存。

这样不仅能保存String还有其他的很多方法:

而在慕课学习中我的五子棋项目中老师这个写的,这个更好:

@Override
    protected Parcelable onSaveInstanceState() {
        Bundle bundle = new Bundle();
        bundle.putParcelable(INSTANCE, super.onSaveInstanceState());

        bundle.putBoolean(INSTANCE_GAME_OVER, mIsGemeoVer);
        bundle.putParcelableArrayList(INSTANCE_WHITE_ARRAY, mWhiteArray);
        bundle.putParcelableArrayList(INSTANCE_BLACK_ARRAY, mBlackArray);

        return bundle;
    }

    @Override
    protected void onRestoreInstanceState(Parcelable state) {
        if (state instanceof Bundle) {
            Bundle bundle = (Bundle) state;

            mIsGemeoVer = bundle.getBoolean(INSTANCE_GAME_OVER);
            mWhiteArray = bundle.getParcelableArrayList(INSTANCE_WHITE_ARRAY);
            mBlackArray = bundle.getParcelableArrayList(INSTANCE_BLACK_ARRAY);

            super.onRestoreInstanceState(bundle.getParcelable(INSTANCE));
            return;
        }
        super.onRestoreInstanceState(state);
    }

老师用的是 Parcelable 与 Bundle结合将全部的传递的参数进行打包了。

关于Parcelable 类我查查了资料,他的作用和Serializable作用差不多,都是序列化,Parcelable 内容还挺多的,推荐瞅瞅这个:http://www.cnblogs.com/renqingping/archive/2012/10/25/Parcelable.html 写的挺好的。

情况二具体:

情况二不好直观的表现出来,但是数据存储恢复过程和上边是一样的,只提一下Activity中优先级的情况。

最高:前台的Activity--正在和用户交互的Activity,这样的级别最高,一般肯定不会给枪毙的。

其次:可见但非前台的Activity--比如Activity中弹出一个对话框,导致Activity可见但是位于后台无法和用户直接交互

最低:后台Activity--已经暂停的Activity,比如执行onStop的,优先级别最低,最容易杀死。

我们还有一种方式使数据不会消失,就是使用钉死AndroidManifest方法。

已知我们的某些系统配置出现改变时就会View就会被重建,我们可以不让它重建就可以了,我们可以给Activity制定configChanges属性,我们可以在AndroidMainifest

中进行配置,比如我们想让他在旋转屏幕的时候不发生重建,我们可以添加:android:configChanges="orientation 属性。

configChanges还有其他许多的属性:

mnc:IMSI网络发生改变,检测到SIM卡,或者更新MCC<span style="font-family: Arial, Helvetica, sans-serif;">其中mcc和mnc理论上不可能发生变化</span>
locale:语言发生改变,用户选择了一个新的语言,文字应该重新显示
touchscreen:触摸屏发生改变,这通常是不应该发生的
keyboard:键盘类型发生改变,例如,用户使用了外部键盘
keyboardHidden:键盘发生改变,例如,用户使用了硬件键盘
navigation:导航发生改变,(这通常不应该发生) 举例:连接蓝牙键盘,连接后确实导致了navigation的类型发生变化。因为连接蓝牙键盘后,我可以使用方向键来navigate了
screenLayout:屏幕的布局发生改变,这可能导致激活不同的显示
fontScale:全局字体大小缩放发生改变
orientation:设备旋转,横向显示和竖向显示模式切换。
screenSize: 屏幕大小改变了
smallestScreenSize: 屏幕的物理大小改变了,如:连接到一个外部的屏幕上

这些属性可以并行使用 如:属性间添加“|”号  android:configChanges="orientation|screenSize" 即可,这样写的话在发生属性这些事件的时候,Activity就不会重建。

//notes:为了防止在旋转屏幕的时候Activity重启除了orientation属性还要添加screenSize

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.hejingzhou.activityleft">
    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".MainActivity" android:configChanges="orientation|screenSize">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>
</manifest>

我们在Activity类中覆写一个onConfigurationChanged()方法打印一下log看看:

  @Override
    public void onConfigurationChanged(Configuration newConfig) {
        super.onConfigurationChanged(newConfig);
        Log.i(TAG,""+newConfig.orientation);
    }
com.example.hejingzhou.activityleft I/com.example.hejingzhou.activityleft.MainActivity: 2
com.example.hejingzhou.activityleft I/com.example.hejingzhou.activityleft.MainActivity: 1

这就是在上一个方法的基础上添加后的进行旋转屏幕的全部log了 可以看出整个过程他就没有调用第一个方法中onRestoreInstanceState方法和onSaveInstanceState

方法,效果是一样的,填写的数据并没有丢失。

时间: 2024-10-31 05:41:26

异常情况下的生命周期分析的相关文章

Activity在异常情况下的生命周期——Android开发艺术探索笔记

欢迎转载,转载请注明出处 http://blog.csdn.net/l664675249/article/details/50638398 Activity在异常情况下的生命周期 关于Activity正常情况下的生命周期请参考这篇文章,本文主要讲解Activity在异常情况下的生命周期. 情况1:资源相关的系统配置发生改变 资源相关的系统配置发生改变,举个栗子.当前Activity处于竖屏状态的时候突然转成横屏,系统配置发生了改变,Activity就会销毁并且重建,其onPause, onSto

Activity 各种情况下的生命周期总结

Situation1: 正常启动: onCreate()  →   onStart()  →  onResume(); 返回健退出: onPause()  →   onStop()  →   onDestory(); Situation2: 正常启动 : onCreate()  →   onStart   →  () onResume(); 按home健: onPause()  →   onStop(); 正常启动:onRestart()  →   onStart()   →  onResume

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

情况1:资源相关的系统配置发生改变 资源相关的系统配置发生改变,举个栗子.当前Activity处于竖屏状态的时候突然转成横屏,系统配置发生了改变,Activity就会销毁并且重建,其onPause, onStop, onDestory均会被调用.因为实在异常情况下终止的,所以系统会调用onSaveInstanceState来保存当前Activity状态.这个方法是在onStop之前,与onPause没有固定的时序关系.当Activity重建的时候系统会把onSaveInstanceState所保

Activity 在横竖屏切换情况下的生命周期变化

title: Activity 在横竖屏切换情况下的生命周期变化 date: 2018-04-26 23:05:57 tags: [Activity] categories: [Mobile,Android] --- 概述 Activity 在横竖屏切换的时候,生命周期是不一样的,本地通过打印 log 的方式,看下区别.测试的机器是 Android6.0 . 不做任何配置的情况下 第一次启动 D/LifeCircleActivity: onCreate() called with: savedI

ViewController的生命周期分析和使用

ViewController的生命周期分析和使用 一.结构 按结构可以对iOS的所有ViewController分成两类: 1.主要用于展示内容的ViewController,这种ViewController主要用于为用户展示内容,并与用户交互,如UITableViewController,UIViewController. 2.用于控制和显示其他ViewController的ViewController.这种ViewController一般都是一个ViewController的容器.如UINa

Fragment(四)Fragment生命周期分析(转)

Fragment(四)Fragment生命周期分析 转载请注明:http://blog.csdn.net/liaoqianchuan00/article/details/24271607   例子一 从Layout中加载Fragment:   假设我们有一个Activity的Layout中有两个Fragment: <LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools=

12、Cocos2dx 3.0游戏开发找小三之3.0中的生命周期分析

重开发人员的劳动成果.转载的时候请务必注明出处:http://blog.csdn.net/haomengzhu/article/details/27706303 生命周期分析 在前面文章中我们执行了第一个 Cocos2d-x 游戏,同一时候也介绍了控制游戏生命周期的 AppDelegate 文件. 以下我们将结合一些游戏调试经常使用的技巧以及VS工具调试的方法来分析 Cocos2d-x 程序的生命周期. VS工具调试 1.查看内存窗体 2.查看输出窗体 3.假设程序崩溃查看调用堆栈窗体 打开项目

盘点异常情况下的紧急处理

盘点异常情况下的紧急处理: update kwkctab set kcl = (select pdl from view_kw10 where view_kw10.itemno = kwkctab.itemno and view_kw10.KW = kwkctab.KWand view_kw10.gys = kwkctab.gysand view_kw10.pdl is not null)  where kwkctab.itemno in (select itemno from view_kw1

Unity3D脚本(MonoBehaviour)生命周期分析

欢迎来到unity学习.unity培训.unity企业培训教育专区,这里有很多U3D资源.U3D培训视频.U3D教程.U3D常见问题.U3D项目源码,我们致力于打造业内unity3d培训.学习第一品牌. 场景中有2个物体:A,B 每个物体上绑定2个脚本:A,B 初始化log: Object : A , Script : B , Message : Awake Object : A , Script : B , Message : OnEnable Object : A , Script : A