关于Activity和Fragment生命周期详细解析

一:关于Activity的生命周期

onCreate() 表示Activity正在被创建

onRestart() 表示Activity正在被重新启动

onStart() 表示Activity正在被启动 即将开始 但是已经可见 但是还没出现在前台

onResume() 表示Activity已经可见 并且出现在前台开始活动

onPause() 表示Activity正在停止 正常情况下 紧接着onStop()就会被调用

onStop() 表示Activity即将停止 可以做一些稍微重量级的回收工作 同样不能太耗时

onDestory() 表示Activity即将被销毁 这是最后一个生命周期的回调 可以做销毁操作

 

关于各种情况下走的生命周期

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

2.onStart() onResume() onstop() 实质有什么不同

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

假设当前Activity为A 如果这个时候打开一个新的Activity B 那么B的onResume() 和 A 的onPause()那个先执行 ,这个时候会先执行A的onPause() 新的Activity才能启动 官方文档中解释了不能在onPause()做重量级操作 因为必须onPause()执行完成以后 新的Activity才能Resume()

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

3.当Activity被异常终止时 如何恢复到原来的模样

关于保存和恢复View层次结构 系统的工作流程是这样的

首先Activity被意外终止时 Activity会调用onSaveInstanceState去保存数据 然后Activity会委托Window去保存数据 接着Window再委托它上面的顶级容器去保存数据 顶级容器是一个ViewGroup,但是一般情况下很可能是一个DecorView 最后顶层容器再去通知它的子元素来保存 这是一个典型的委托思想 上层委托下层 父容器委托子元素去处理一件事

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

4.内存资源不足时导致优先级低的Activity被杀死

5.Activity按照优先级从高到低

①:前台Activity 正在和用户交互的Activity优先级最高

②:可见但非前台Activity 比如Activity弹出了一个对话框 导致Activity可见但是不能和用户直接交互

③:后台Activity 已经被暂停的Activity优先级最低 比如执行了onStop 优先级最低

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

 

关于Activity的启动模式

1.standard 标准模式 也就是默认模式 每次启动一个Activity都会重新创建一个新的实例 不管这个实例是否已经存在 在这个模式下 谁启动了Activity 那么这个Activity就启动它的那个Activity所在的栈中

 

2.singleTop 栈顶复用模式 在这个模式下 如果新的Activity已经位于任务栈顶 那么Activity不会被重新创建 同时它的onNewIntent方法会被回调 通过此方法的参数我们可以去除当前的请求信息

 

3.singleTask 栈内复用模式 这是一个单例模式 在这种模式下 只要Activity在一个栈中存在 那么措辞启动此Activity都不会创建实例 和singleTop是一样 系统也会调用onNewIntent 这个就是singleTask有clearTop的效果 会导致栈内已经存在的Activity全部出栈

 

4.singleInstance 单实例模式 这个模式是一种加强的singleTask模式 它除了singleTask所具有的特性意外 还加强了一点 那就是具有此模式的Activity只能单独位于一个任务栈中 比如Activity A是singleInstace模式 当A启动后 系统会为他创建一个新的任务栈 然后A独自在这个新的任务栈中 由于栈内复用的特性 后续均不会创建新的Activity 除非这个独特的任务栈被销毁

 

关于Activity切换横竖屏

切换Activity横竖屏会走回调两个函数

onSaveInstanceState(Bundle outState);在Activity即将销毁时保存数据

onRestoreInstanceState(Bundle saveInstanceState);Activity重建时恢复或者取出数据

启动进入

Activity→onCreate()→onStart()→onResume()

旋转屏幕

onPause()→onSaveInstanceState()→onStop()→onDestory()→onCreate()→onStart()→onRestoreInstanceState()→onResume()

再次旋转屏幕

onPause()→onSaveInstanceState()→onStop()→onDestory()→onCreate()→onStart()→onRestoreInstanceState()→onResume()

 

******在Manifest.xml中设置andoid:configChanges="orientation|screenSize"切换不会重新调用各个生命周期,而只会执行onConfigurationChanged方法

*****MiniSdkVersion大于等于13的时候 android:configChanges="orientation"或者android:configChanges="orientation|keyboardHidden"重新调用各个生命周期

*****不设置Activity的configChanges时,切屏会重新调用各个生命周期 切换横屏会执行一次 切换竖屏会执行两次

*****设置configChanges="orientation",切屏还是会走各个生命周期 但是横竖都只会走一次

*****Android横竖屏切换在手机开发中比较常见,很多软件在开发过程中为了避免横竖屏切换时引发不必要的麻烦,通常禁止掉横竖屏的切换。

  一、在AndroidManifest.xml中设置activity中的android:screenOrientation属性值来实现。

      (1)竖屏:android:screenOrientation="portrait"

      (2)横屏:android:screenOrientation="landscape"

  二、在Java代码中通过类似如下代码来设置 (不推荐这种方法,在大的app不同方向启动时会慢)

      (1)竖屏: setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT)

      (2)横屏:setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE)

  三、如果要彻底禁止翻转,忽略重力感应带来的切换,(模拟器上不管用,在真机上是正确的)

      (1)忽略重力:android:screenOrientation="nosensor"

 

****横竖屏辨识

一、在onConfigurationChanged里判断,为了onConfigurationChanged在监听屏幕方向变化有效需要以下条件

(1)AndroidManifest.xml增加权限:<uses-permission android:name="android.permission.CHANGE_CONFIGURATION"></uses-permission>

(2)AndroidManifest.xml里设置的MiniSdkVersion和 TargetSdkVersion属性大于等于13

(3)在AndroidManifest.xml的Activity里增加:android:configChanges="keyboard|screenSize|orientation|layoutDirection"

(4)在onConfigurationChanged(Configuration newConfig)进行判断

@Override

public void onConfigurationChanged(Configuration newConfig) {

super.onConfigurationChanged(newConfig);

if(newConfig.orientation == 1)//竖屏

if(newConfig.orientation == 2)// 横屏

}

 

二、因为当屏幕变为横屏的时候,系统会重调用Activity的onCreate方法可以在onCreate中来检查当前的方向,然后可以让你的setContentView来载入不同的layout xml。

if (this.getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE){

        Log.i("info","landscape"); // 横屏

} else if(this.getResources().getConfiguration().orientation ==Configuration.ORIENTATION_PORTRAIT) {

        Log.i("info","portrait"); // 竖屏

}

     注意:该方法是在AndroidManifest.xml中不设置onConfigurationChanged才能重走生命周期

 

*****横竖屏切换布局文件设置

如果要让软件在横竖屏之间切换,由于横竖屏的高宽会发生转换,有可能会要求不同的布局。可以通过以下方法来切换布局

(1)在res目录下建立layout-land和layout-port目录,相应的layout文件名称不变,比如main.xml。layout-land是横屏的layout,layout-port是竖屏的layout,其他的不用管,模拟器会自动寻找。

(2)在上面横竖屏辨识中,如果横竖屏出现变化,在onCreate()或者onConfigurationChanged()判断方向,就可以在相应的方法中重新setContentView来载入不同的layout xml布局文件

横竖屏切换数据保存与读取

另外,android中每次屏幕的切换动会重启Activity,所以应该在Activity销毁前保存当前活动的状态,在Activity再次Create的时候载入配置,那样,进行中的游戏就不会自动重启了!

Activity 数据保存

(1)如果因为系统资源紧张而导致Activity的Destory或者旋转屏幕时被destroyed与Recreated, 系统会在用户回到这个Activity时有这个Activity存在过的记录,系统会使用那些保存的记录数据(instance state)它是一些存放在Bundle对象中的key-value pairs,系统默认使用 Bundle保存信息

(2)为了可以保存额外更多的数据到instance state,要重写写这个回调函数onSaveInstanceState(Bundle outState),系统会在Activity被异常Destory时传递Bundle对象,这样我们就可以增加额外的信息到Bundle中并保存到系统中。若系统在Activity被Destory之后想重新创建这个Activity实例时,之前的Bundle对象会(系统)被传递到你我们activity的

(3)Activity开始stop,系统会调用 onSaveInstanceState(Bundle outState) ,Activity可以用键值对的集合来保存状态信息。这个方法会默认保存Activity视图的状态信息,如在 EditText组件中的文本或 ListView 的滑动位置

Activity 数据恢复

(1)当Activity从Destory中重建,我们可以从系统传递的Activity的Bundle中恢复保存的状态。 onCreate() 与 onRestoreInstanceState() 回调方法都接收到了同样的Bundle,里面包含了同样的实例状态信息。

(2)由于 onCreate() 方法会在第一次创建新的Activity实例与重新创建之前被Destory的实例时都被调用,我们必须在尝试读取 Bundle 对象前检测它是否为null。如果它为null,系统则是创建一个新的Activity实例,而不是恢复之前被Destory的Activity。

(3)也可以选择实现 onRestoreInstanceState() ,而不是在onCreate方法里面恢复数据。 onRestoreInstanceState()方法会在 onStart() 方法之后执行. 系统仅仅会在存在需要恢复的状态信息时才会调用 onRestoreInstanceState() ,因此不需要检查 Bundle 是否为null

 

一:关于Fragment的生命周期

 

onAttach:onAttach()在fragment与Activity关联之后调调查用。需要注意的是,初始化fragment参数可以从getArguments()获得,但是,当Fragment附加到Activity之后,就无法再调用setArguments()。所以除了在最开始时,其它时间都无法向初始化参数添加内容。

 

onCreate:fragment初次创建时调用。尽管它看起来像是Activity的OnCreate()函数,但这个只是用来创建Fragment的。此时的Activity还没有创建完成,因为我们的Fragment也是Activity创建的一部分。所以如果你想在这里使用Activity中的一些资源,将会获取不到。比如:获取同一个Activity中其它Frament的控件实例。(代码如下:),如果想要获得Activity相关联的资源,必须在onActivityCreated中获取。

 

onCreateView:在这个fragment构造它的用户接口视图(即布局)时调用。

 

onActivityCreated:在Activity的OnCreate()结束后,会调用此方法。所以到这里的时候,Activity已经创建完成!在这个函数中才可以使用Activity的所有资源。如果把下面的代码放在这里,获取到的btn_Try的值将不会再是空的!

 

onStart:当到OnStart()时,Fragment对用户就是可见的了。但用户还未开始与Fragment交互。在生命周期中也可以看到Fragment的OnStart()过程与Activity的OnStart()过程是绑定的。意义即是一样的。以前你写在Activity的OnStart()中来处理的代码,用Fragment来实现时,依然可以放在OnStart()中来处理。

 

onResume:当这个fragment对用户可见并且正在运行时调用。这是Fragment与用户交互之前的最后一个回调。从生命周期对比中,可以看到,Fragment的OnResume与Activity的OnResume是相互绑定的,意义是一样的。它依赖于包含它的activity的Activity.onResume。当OnResume()结束后,就可以正式与用户交互了。

 

onPause:此回调与Activity的OnPause()相绑定,与Activity的OnPause()意义一样。

 

onStop:这个回调与Activity的OnStop()相绑定,意义一样。已停止的Fragment可以直接返回到OnStart()回调,然后调用OnResume()。

 

onDestroyView:如果Fragment即将被结束或保存,那么撤销方向上的下一个回调将是onDestoryView()。会将在onCreateView创建的视图与这个fragment分离。下次这个fragment若要显示,那么将会创建新视图。这会在onStop之后和onDestroy之前调用。这个方法的调用同onCreateView是否返回非null视图无关。它会潜在的在这个视图状态被保存之后以及它被它的父视图回收之前调用。

 

onDestroy:当这个fragment不再使用时调用。需要注意的是,它即使经过了onDestroy()阶段,但仍然能从Activity中找到,因为它还没有Detach。

 

onDetach:Fragment生命周期中最后一个回调是onDetach()。调用它以后,Fragment就不再与Activity相绑定,它也不再拥有视图层次结构,它的所有资源都将被释放。

 

 

 

 

 

 

 

 

 

 

 

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值