您的位置:首页 > 移动开发 > Android开发

Android核心基础-8.Android四大组件之Activity-3.生命周期、横竖屏切换、启动模式、进程管理

2015-09-04 20:31 1121 查看

8.3.1 Activity三种状态

运行:activity在最前端运行

停止:activity不可见,完全被覆盖

暂停:activity可见,但前端还有其他activity

8.3.2 Activity生命周期相关方法

生命周期相关方法

onCreate(创建):创建时调用,或者程序在暂停、停止状态下被杀死之后重新打开时也会调用

onStart(可见):onCreate之后或者从停止状态恢复时调用

onResume(获得焦点):onStart之后或者从暂停状态恢复时调用,从停止状态恢复时由于调用onStart,也会调用onResume

onPause(失去焦点):进入暂停、停止状态,或者销毁时会调用

onStop(不可见):进入停止状态,或者销毁时会调用

onDestroy(销毁):销毁时调用

onRestart(从不可见恢复到可见):从停止状态恢复时调用

activity_lifecycle



场景分析

1.点击桌面图标启动一个应用

onCreate()->onStart()->onResume()

2.点击返回键退出应用

onPause()->onStop()->onDestroy()

3.点击Home键将应用退到后台

4.当前应用展示着,此时长按Home键打开其他应用,当前应用会执行

onPause()->onStop()

5.将点击Home键退到后台的应用重新打开

onRestart()->onStart()->onResume()

6.将点击Home键退到后台的应用从Home中移除

onDestroy()

7.应用打开着的,此时来了一个电话☎

onPause()->onStop()

8.续7对方将电话挂断

onRestart()->onStart()->onResume()

9.续7自己将电话挂断

onRestart()->onStart()->onResume()

10.在应用中启动其他程序(播放一首音乐)

onPause()

11.续10此时再点击返回键退出播放器

onResume()

public void play(View v) {
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(Uri.parse("file:///mnt/sdcard/Music/1.mp3"), "audio/*");
startActivity(intent);
}




12.续10如果点击一个按钮弹出一个Dialog

将不执行任何生命周期

public void play(View v) {
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(Uri.parse("file:///mnt/sdcard/Music/1.mp3"), "audio/*");
startActivity(intent);

OnClickListener listener = new OnClickListener() {

@Override
public void onClick(DialogInterface dialog, int which) {
switch (which) {
case DialogInterface.BUTTON_POSITIVE:
Toast.makeText(getApplicationContext(), "确定", Toast.LENGTH_SHORT).show();
break;

case DialogInterface.BUTTON_NEGATIVE:
Toast.makeText(getApplicationContext(), "稍后", Toast.LENGTH_SHORT).show();
break;

case DialogInterface.BUTTON_NEUTRAL:
Toast.makeText(getApplicationContext(), "取消", Toast.LENGTH_SHORT).show();
break;
}
}
};
new AlertDialog.Builder(this)
.setTitle("是否下载更新")
.setMessage("1.速度更快\n2.更多功能\n3.修复上个版本的Bug")
.setPositiveButton("确定", listener)
.setNegativeButton("稍后", listener)
.setNeutralButton("取消", listener)
.setCancelable(false).show();
}


补充说明

按返回键,程序退出,但是程序的
进程
还保存着,目的是下次启动时可以更快速。

长按Home键,将程序从其中移除,此时程序的进程将被移除。



8.3.3 Activity横竖屏切换

模拟器横竖屏切换:Ctrl+F11或者Ctrl+F12

默认情况下横竖屏切换生命周期(摧毁重建):
onPause()->onStop()->onDestroy()->onCreate()->onStart()->onResume()


a.默认情况下, 横竖屏切换时会摧毁Activity重构, 因为要进行屏幕适配.

可以使用onSaveInstanceState()保存数据, 用onRestoreInstanceState()恢复数据

onSaveInstanceState()在Activity失去焦点时也会被调用, 如果Activity在后台被杀死了, 再次启动时会自动调用onRestoreInstanceState()

b.如果不需要屏幕适配, 那么可以通过定义属性控制Activity不摧毁重构

android:configChanges=”orientation|screenSize”

这种情况下不执行任何生命周期方法, 也不会改变布局

c.固定Activity方向

android:screenOrientation=”portrait”

在这种情况下, Activity不会摧毁重构, 也不会改变方向

d.相关代码

getResources().getConfiguration().orientation

setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE)

setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT)

8.3.3.1如果要做横竖屏切换,且布局要发生改变

那么要配置对应的横竖屏布局文件:
资源文件目录
横版:res/layout-land/activity_main.xml
竖版:res/layout-port/activity_main.xml
如上配置好资源文件后,当横竖版切换时,会自动读取对应布局文件,重新渲染生成界面。
生命周期方法执行:onPause()->onSaveInstanceState()->onStop()->onDestroy()->onCreate()->onStart()->onRestoreInstanceState()->onResume()

按Home键:onPause()->onSaveInstanceState()->onStop()
再从Home键中打开:onRestart()->onStart()->onResume()

按Home键退到后台,隔了好长时间被系统自动垃圾回收了(即程序的进程被系统杀死了),
此时再从Home中打开:onCreate()->onStart()->onRestoreInstanceState()->onResume()


附加:从这里我们可以知道这个Bundle存储的数据是持久化的保存在本地文件系统中(而不是在内存中)

8.3.3.2跟随手机横竖屏切换,但是不会摧毁重建,即横竖屏都使用同一个布局文件

在清单文件中的activity节点中配置:android:configChanges="orientation"
那么即便该activity被手机自动横竖屏切换,也不会执行任何生命周期方法(即不会被摧毁重建)
在android3.2版本以后要这么配置
android:configChanges="orientation|screenSize"


8.3.3.3固定方向,手机横竖拿都不改变方向

固定Activity的方向(即手机横竖拿当前Activity都是固定的一个方向)
在清单文件中的activity节点中配置:
android:screenOrientation="portrait"竖屏
landscape 横屏
sensorPortrait 在两个竖屏间切换
sensorLandscape 在两个横屏间切换
sensor 右、下、左三个方向切换(也有四个方向切换,与系统有关)
fullSensor 四个方向都可切换
unspecified 将会跟随系统(即用户手机开启方向锁:不可切换;关闭方向锁:四个方向可切换)默认为该属性
user效果同unspecified
behind效果同unspecified
nosensor不可切换
reverseLandscape固定横屏但同landscape方向相反
reversePortrait固定竖屏但同portrait方向相反
userLandscape 在两个横屏间切换(前提:用户手机关闭方向锁定)
userPortrait 在两个竖屏间切换(前提:用户手机关闭方向锁定)
fullUser四个方向都可切换(前提:用户手机关闭方向锁定)
locked方向锁定不可切换


附加说明:在两个横屏或者两个竖屏间切换不会触发生命周期(即不会摧毁重建)

8.3.3.4代码控制横竖屏切换

生命周期是否执行,同前面所讲

public void change(View v) {
switch (getResources().getConfiguration().orientation) {    // 获取屏幕方向
case Configuration.ORIENTATION_LANDSCAPE:               // 横屏
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);  // 改为竖屏
break;
case Configuration.ORIENTATION_PORTRAIT:                // 竖屏
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE); // 改为横屏
break;
}
}


示例源码->百度网盘

8.3.4启动模式

在AndroidManifest.xml中的标签中可以配置android:launchMode属性,用来控制Actvity的启动模式

在Android系统中我们创建的Acitivity是以栈的形式呈现的

a.standard: 每次调用startActivity()启动时都会创建一个新的Activity放在栈顶—>每次都启动一个新的(默认)

b.singleTop: 启动Activity时,指定Activity不在栈顶就创建,如在栈顶,则不再创建—>不能自己创建自己

c.singleTask: 如果启动的Activity不存在就创建,如果存在直接跳转到指定的Activity所在位置—>启动哪个, 就把它上面的出栈

d.singleInstance: 如果启动的Activity不存在就创建,如果存在就将指定的Activity移动到栈顶—>启动哪个就把哪个放在栈顶

standard

每次都启动一个新的:Activity-A可以启动一个新的Activity-A,新的Activity-A又可以启动一个新的Activity-A,每次都是往栈顶压入一个新的。



singleTop

不能自己创建自己:即Activity-A如果在栈顶,则此时再启动一个Activity-A是没效果的,还是当前的自己在栈顶。但可以启动一个Activity-B,最终效果就是两个相同的Activity是不会相邻的。



singleTask

启动哪个, 就把它上面的出栈:如图Activity-A在栈底,此时如果Activity-C要启动Activity-A,那么结果将会是将Activity-A之上的都出栈(即Activity-B和Activity-C都出栈,只剩下Activity-A在栈中)



singleInstance

启动哪个就把哪个放在栈顶:整个栈中只会保留一个Activity-A,Activity-B,Activity-C;

如图:Activity-C要启动Activity-A,则将会把Activity-A移至栈顶;如果此时Activity-A又要启动Activity-B,则将会把Activity-B移至栈顶。如此循环,保证栈中唯一实例对象。

(附加说明:在这里其实是一个Activity就独占一个栈,然后一个大的栈又装载了这些小的栈。上面的讲法是为了方便理解,望读者知晓)



代码中设置

Intent intent = new Intent(this, A_Activity.class);

//默认的跳转类型,将Activity放到一个新的Task中(同standard)
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

//如果Activity已经运行到了Task,再次跳转不会再运行这个Activity(同singleTop)
intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);

//如果activity在Task存在,将Activity之上的所有Activity结束掉(同singleTask)
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);

//如果activity在Task存在,拿到最顶端,不会启动新的Activity(同singleInstance)
intent.addFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT);


示例源码->百度网盘

8.3.5 进程管理

Android系统在运行多个进程时,如果系统资源不足,会强制结束一些进程。优先选择哪个进程来结束是有优先级的。

空: 进程中没有任何组件

后台:进程中只有停止状态的Activity

服务:进程中有正在运行的服务

可见:进程中有一个暂停状态的Activity

前台:进程中正在运行一个Activity
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  android 生命周期