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

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
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);
}

播放器-startActivity

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,每次都是往栈顶压入一个新的。
Activity启动模式-standard

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

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

singleInstance
启动哪个就把哪个放在栈顶:整个栈中只会保留一个Activity-A,Activity-B,Activity-C;
如图:Activity-C要启动Activity-A,则将会把Activity-A移至栈顶;如果此时Activity-A又要启动Activity-B,则将会把Activity-B移至栈顶。如此循环,保证栈中唯一实例对象。
(附加说明:在这里其实是一个Activity就独占一个栈,然后一个大的栈又装载了这些小的栈。上面的讲法是为了方便理解,望读者知晓)
Activity启动模式-singleInstance

代码中设置

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系统在运行多个进程时,如果系统资源不足,会强制结束一些进程。优先选择哪个进程来结束是有优先级的。

  1. 空: 进程中没有任何组件
  2. 后台:进程中只有停止状态的Activity
  3. 服务:进程中有正在运行的服务
  4. 可见:进程中有一个暂停状态的Activity
  5. 前台:进程中正在运行一个Activity
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Android设备的幕从横切换为竖,或者从竖切换为横时,Activity生命周期会经历以下过程: 1. onPause(): 在幕旋转之前,系统会调用当前Activity的onPause()方法。这表示Activity正在失去焦点,并即将进入停止状态。 2. onSaveInstanceState(): 在幕旋转之前,系统会调用当前Activity的onSaveInstanceState()方法,用于保存Activity的状态信息。你可以在此方法中保存必要的数据,以便在Activity重新创建后进行恢复。 3. onStop(): 当幕旋转完成并且新的布局已经加载完毕后,系统会调用当前Activity的onStop()方法。此时,Activity已经完全不可见。 4. onDestroy(): 如果幕旋转导致当前Activity被销毁并重新创建,则系统会调用当前Activity的onDestroy()方法。你可以在此方法中释放资源和执行清理操作。 5. onCreate(): 在幕旋转导致Activity重新创建时,系统会调用当前Activity的onCreate()方法。你可以在此方法中重新初始化UI和恢复之前保存的数据。 6. onStart(): 在幕旋转之后,系统会调用当前Activity的onStart()方法。此时,Activity已经可见,但还没有获得焦点。 7. onResume(): 最后,系统会调用当前Activity的onResume()方法。在此方法中,你可以恢复之前的操作,并开始响应用户的交互。 需要注意的是,当幕旋转时,Activity会被销毁并重新创建,因此需要适当地处理数据保存和恢复的逻辑,以保证用户体验的连续性。可以使用onSaveInstanceState()方法保存和恢复Activity的状态信息,在onCreate()和onRestoreInstanceState()方法中进行处理。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值