Android开发 View与Activity的生命周期[转载]

Android每周专题】横竖屏切换ActivityView状态的保持 每周专题名不符实,实在是惭愧,前段时间有点忙,没有及时更新,自我反省一下。 本周专题分为两个部分,第一部分是横竖屏切换的相关问题,第二部分是ActivityView状态的保持。 横竖屏切换 一、横竖屏切换时Activity生命周期 1、启动Activity(竖屏时启动的) 11-01 01:48:17.144: I/a2bgeek(945): onCreate 11-01 01:4 阅读详情

作者:sososeen09
链接:https://www.jianshu.com/p/0a4cb44ce9d1
来源:简书

前言

Activity有生命周期,同样的,View从添加到界面到从界面中移除也有一个生命周期,在官方文档中介绍了自定义View需要重写的一些方法,可以认为这些方法就是View的生命周期方法。

View的生命周期方法.png

本文就介绍一下这些方法调用的顺序流程以及与Activity的生命周期结合之后的顺序流程。

View的生命周期

从Activity启动到退出,这个View 的过程是这样的。

D/ViewLifeTestView: ViewLifeTestView: construct 
D/ViewLifeTestView: onFinishInflate: 
D/ViewLifeTestView: onAttachedToWindow: 
D/ViewLifeTestView: onWindowVisibilityChanged: visiable
D/ViewLifeTestView: onMeasure: 
D/ViewLifeTestView: onMeasure: 
D/ViewLifeTestView: onSizeChanged: 
D/ViewLifeTestView: onLayout: 
D/ViewLifeTestView: onDraw: 
D/ViewLifeTestView: onWindowFocusChanged: true
D/ViewLifeTestView: onWindowVisibilityChanged: gone
D/ViewLifeTestView: onWindowFocusChanged: false
D/ViewLifeTestView: onDetachedFromWindow: 

Paste_Image.png

在Activity的onCreate()方法中调用setContentView方法,Activity显示到界面时的View的回调

  1. 构造方法,这是肯定的,View也是一个Java类。
  2. onFinishInflate,这个一般是通过LayoutInflater进行填充的时候会走这个方法。如果我们是直接在代码中new出来的View进行添加,是不会走这个方法的。
  3. onAttachedToWindow,这个方法表明现在这个View已经跟它对应的Window已经绑定了
  4. onWindowVisibilitChanged(int visibility) ,这个值等于 View.VISIBLE,代表View所在的Window已经可见了。
  5. onMeasure,开始测量。我们发现,这个measure过程是在Window可见的情况下才会去调用了,仔细想想这个也不难理解,如果你都不准备显示,我何必去花精力测量你呢。这个测量过程可能会多次调用。
  6. onSizeChanged ,测量之后会回调这个方法。onSizeChanged,顾名思义就是当尺寸发生变化的时候会调用。一般是第一次测量之后调用,后面再测量,如果尺寸没变化就不会再去调用了。
  7. onLayout,测量时候就进行布局,这个时候如果是View的话一般不用去管,因为具体放在哪个位置是由父控件去控制的,如果是ViewGroup,就需要去确定子View的位置。
  8. onDraw,确定完位置和宽高,就可以进行绘制了。
  9. onWindowFocusChanged(boolean hasWindowFocus),为true这个说明View所绑定的Window开始获取焦点

当按back键退出当前Activity后,走下面几个方法

  1. onWindowVisibilitChanged(int visibility) ,这个值等于 View.GONE,此时Window已经不可见了
  2. onWindowFocusChanged(boolean hasWindowFocus),这个也变为false,说明已经没有焦点了。有一点比较奇怪,为什么是先不可见才是没有焦点的呢?
  3. onDetachedFromWindow, 当前View与它对应的Window解除绑定。

Activity和View的生命周期结合

当Activity和View的生命周期结合,我们会发现一些有意思的东西。

D/ViewLifeTestActivity: onCreate: 
D/ViewLifeTestActivity: onWindowAttributesChanged: 
...
D/ViewLifeTestView: ViewLifeTestView: construct 
D/ViewLifeTestView: onFinishInflate: 
D/ViewLifeTestActivity: onStart: 
D/ViewLifeTestActivity: onWindowAttributesChanged: 
D/ViewLifeTestActivity: onResume: 
D/ViewLifeTestActivity: onAttachedToWindow: 
D/ViewLifeTestView: onAttachedToWindow: 
D/ViewLifeTestView: onWindowVisibilityChanged: visiable
D/ViewLifeTestView: onMeasure: 
D/ViewLifeTestView: onMeasure: 
D/ViewLifeTestView: onSizeChanged: 
D/ViewLifeTestView: onLayout: 
D/ViewLifeTestView: onDraw: 
D/ViewLifeTestActivity: onWindowFocusChanged hashFocus: true
D/ViewLifeTestView: onWindowFocusChanged: true
D/ViewLifeTestView: onTouchEvent: 
D/ViewLifeTestActivity: onPause: 
D/ViewLifeTestView: onWindowVisibilityChanged: gone
D/ViewLifeTestActivity: onWindowFocusChanged hashFocus: false
D/ViewLifeTestView: onWindowFocusChanged: false
D/ViewLifeTestActivity: onStop: 
D/ViewLifeTestActivity: onDestroy: 
D/ViewLifeTestView: onDetachedFromWindow: 
D/ViewLifeTestActivity: onDetachedFromWindow: 

结合与Activity的启动过程可以看到

  1. Activity 调用onCreate方法,这个时候我们setContentView加载了带View的布局
  2. Activity 调用onWindowAttributesChanged 方法,而且这个方法连续调用多次
  3. View 调用构造方法
  4. View 调用onFinishInflate方法,说明这个时候View已经填充完毕,但是这个时候还没开始触发绘制过程
  5. Activity 调用onstart方法
  6. Activity 再次调用 onWindowAttributesChanged 方法,说明这个方法在onResume之前会多次调用
  7. Activity 调用onResume,我们一般认为当Activity调用onResume的时候,整个Activit已经可以和用户进行交互了,但事实上可能并不是这样,后面解释原因。
  8. Activity 调用onAttachedToWindow,说明跟Window进行了绑定。发现了吗,Activity在onResume之后才跟Window进行了绑定。
  9. View 调用onAttachedToWindow,View开始跟Window进行绑定,这个过程肯定是在Activity绑定之后才进行的。
  10. View 调用 onWindowVisibilityChanged(int visibility),参数变为 View.VISIABLE,说明Window已经可见了,这个时候我们发现一个问题就是其实onResume的时候似乎并不代表Activity中的View已经可见了。
  11. View 调用onMeasure,开始测量
  12. View 调用onSizeChanged,表示测量完成,尺寸发生了变化
  13. View 调用onLayout,开始摆放位置
  14. View 调用 onDraw,开始绘制
  15. Activity 调用onWindowFocusChanged(boolean hasFocus),此时为true,代表窗体已经获取了焦点
  16. View 调用 onWindowFocusChanged(boolean hasWindowFocus),此时为true,代表当前的控件获取了Window焦点,当调用这个方法后说明当前Activity中的View才是真正的可见了。

当退出当前的Activity的时候

  1. Activity 调用 onPause
  2. View 调用 onWindowVisibilityChanged(int visibility),参数变为 View.GONE,View中对应的Window隐藏
  3. Activity 调用onWindowFocusChanged(boolean hasFocus),此时为false,说明Actvity所在的Window已经失去焦点
  4. Activity 调用 onStop,此时Activity已经切换到后台
  5. Activity 调用 onDestory,此时Activity开始准备销毁,实际上调用onDestory并不代表Activity已经销毁了。
  6. View 调用 onDetachedFromWindow,此时View 与Window解除绑定
  7. Activity 调用 onDetathedFromWindow ,此时Activity 与Window 解除绑定

当View进行与Window解除绑定之后,View即将被销毁。我们可以在 View 的 onDetachedFromWindow 方法中可以做一些资源的释放,防止内存泄漏。

Activity的onWindowFocusChanged(boolean hasFocus)

从上面的分析我们可以知道,一个Activity启动后onCreate、onStart、onResume等过程后,Activity并不是真正可见的,只有当 onWindowFocusChanged 方法最后调用并且参数为true的时候Activity才是真正的可见,这个时候才可以和用户进行交互。

我们可以这 onWindowFocusChanged 可以做一些事情。比如, 获取布局中的控件的尺寸。

从 Activity 中的 onWindowFoucusChanged 方法介绍来看,当包含 View的 Window 获得或者失去焦点就会调用这个方法。而且要注意,它和View的焦点是有区别的。为了接收键盘事件,View和Window都必须获得焦点。而当一个显示在你的Window上面的Window获取输入焦点的时候,你自己的Window失去了焦点,但是这个View本身的焦点不会改变。例如,弹出一个PopopWindow。

下面是 Activity 的 onWindowFocusChanged 方法介绍。

# Activity
/**
 * Called when the window containing this view gains or loses focus.  Note
 * that this is separate from view focus: to receive key events, both
 * your view and its window must have focus.  If a window is displayed
 * on top of yours that takes input focus, then your own window will lose
 * focus but the view focus will remain unchanged.
 *
 * @param hasWindowFocus True if the window containing this view now has
 *        focus, false otherwise.
 */
public void onWindowFocusChanged(boolean hasWindowFocus) {
    InputMethodManager imm = InputMethodManager.peekInstance();
    if (!hasWindowFocus) {
        if (isPressed()) {
            setPressed(false);
        }
        if (imm != null && (mPrivateFlags & PFLAG_FOCUSED) != 0) {
            imm.focusOut(this);
        }
        removeLongPressCallback();
        removeTapCallback();
        onFocusLost();
    } else if (imm != null && (mPrivateFlags & PFLAG_FOCUSED) != 0) {
        imm.focusIn(this);
    }
    refreshDrawableState();
}

在 Activity 的 onResume 方法中,可以看到有这么一段注释。意思就是提醒大家 这个onResume 并不是提醒你这个Activty对用户可见的最佳指示器。例如一个系统Window如键盘可能是处在前面。采用onWindowFocusChanged可以确定当前的Activity对用户可见并且是可交互的。

/**
 * Called after {@link #onRestoreInstanceState}, {@link #onRestart}, or
 * {@link #onPause}, for your activity to start interacting with the user.
 * This is a good place to begin animations, open exclusive-access devices
 * (such as the camera), etc.
 *
 * <p>Keep in mind that onResume is not the best indicator that your activity
 * is visible to the user; a system window such as the keyguard may be in
 * front.  Use {@link #onWindowFocusChanged} to know for certain that your
 * activity is visible to the user (for example, to resume a game).
 *
 * <p><em>Derived classes must call through to the super class's
 * implementation of this method.  If they do not, an exception will be
 * thrown.</em></p>

总结

  1. 熟知 View 的生命周期方法,可加深我们对于View的理解,在开发中也可以根据这个生命周期方法的回调时机来写出更加合理高效的自定义View,例如在 View 的 onDetachedFromWindow 方法中释放资源。
  2. Activity还有其它的生命周期方法,比如 onSaveInstanceState(Bundle outState)onRestoreInstanceState(Bundle savedInstanceState) 等,限于篇幅和主题,本文并没有介绍这些方法,但是其实这些方法在 Activity 的生命周期方法中也是很重要的。
  3. 通常认为Activity的 onResume 方法调用之后,就可以与用户交互,通过本文的分析可知,这种说法并不准确。只有在 Activity 的 onWindowFocusChanged(boolean hasFocus) 调用,并且参数为true的时候,才是真正可以和用户交互的时机。
  4. Activity 和 View 的很多生命周期回调方法都牵涉到 Window,这个Window 是Android 系统中的一个抽象类,它有一个唯一的子类叫作 PhoneWindow, 它具体有什么作用,在以后的文章中会介绍到它。
Rust+Tauri 调用系统原生能力完全指南:桌面 / Android / iOS / HarmonyOS 本文深入探讨了Tauri框架如何通过Rust内核系统WebView实现跨平台开发,打通H5系统能力的交互链路。文章从Tauri的四层架构(前端、WebView、Rust内核、原生层)入手,详细解析了JSRust的IPC通信原理,并横向对比了桌面、Android、iOS、HarmonyOS四端的实现差异。核心结论包括:Tauri采用Rust作为唯一系统能力持有者,通过统一IPC通道连接前端底层;移动端官方支持Android/iOS,鸿蒙需社区扩展;开发者可保持同一套H5代码Rust业务逻辑,仅通过条 阅读详情

相关推荐

5nm制程的CV5芯片实测:用它给无人机做8K拍摄实时避障,功耗性能到底怎么样?

本文深度评测了5nm制程的CV5芯片在无人机8K拍摄实时避障中的表现。通过实测数据展示了CV5的异构计算架构、8K视频编码性能CVflow®AI引擎的加速效果,同时提供了开发中的优化技巧散热建议,为无人机开发者提供了实用的参考。

weixin_30861797的博客 325

Android activity 相关知识点梳理

在正常情况下,Activity 的常用生命周期就只有如下 7 个:1.:表示 Activity 正在被创建,常用来初始化工作,比如调用 setContentView 加载界面布局资源,初始化 Activity 所需数据等;2.:表示 Activity 正在重新启动,一般情况下,当前 Acitivty 从不可见重新变为可见时,OnRestart 就会被调用;3.:表示 Activity 正在被启动,此时 Activity 可见但不在前台,还处于后台,无法用户交互;4.

diuping20110926的博客 1260

Android Performance】进程性能配置三板斧——task_profiles、IO优先级sched_boost调度提升实战

本文系统讲解Android系统中为关键进程"提性能"的三板斧配置手段,以update_engine(OTA升级服务)为贯穿示例。文章先建立全局认知:进程性能受三层资源制约——CPU调度、IO优先级、调度器boost行为,对应三种配置手段各司其职;随后逐一拆解:task_profiles机制(在init rc文件中用一行task_profiles指令为service挂载预定义性能配置组。

weixin_44081096的博客 444

Android 图解Activity生命周期

当用户需要对手机通过屏幕进行交互时,比如打一个电话,拍张照片,发送一个邮件,或者查看地图。开发者就需要实现一个活动(Activity)。每个活动都将作为一个提供用户使用接口的窗口。它可以填满整个屏幕,也可以小于、大于屏幕甚至漂浮在其它窗口上面。作为android应用程序中最重要的四大组件之一。今天我们来学习一下它的生命周期。 首先,创建一个android project,包含两个Activity

yuxlong2010的专栏 3362

Activity生命周期详解(转载文章)

学习总结之用,上图 Activity作为四大组件之一,出现的频率相当高,基本上我们在android的各个地方都能看见它的踪影,因此深入了解Activity,对于开发高质量应用程序是很有帮助的。今天我们就来详细地聊聊Activity生命周期,以便我们在以后的开发中能如鱼得水。 一、初识Activity   在日常应用中Activity用户交互的接口,它提供了一个用户完成相关操作的窗口。当我们在开发中创建Activity后,通过调用setContentView(View)方法来给该Activity指定一

weixin_40862356的博客 2754

Android 开发 Activity里获取View的宽度高度 转载

Android 开发 Activity里获取View的宽度高度 转载 原文地址:https://blog.csdn.net/chenbaige/article/details/77991594 前言: 可能很多情况下,我们都会有在activity中获取view...

weixin_30483697的博客 148

AndroidActivity详解

本篇不针对于新手,而是对于Activity中一些常识或者问题进行总结。本篇介绍了Activity生命周期、启动关闭、状态保存、启动模式、返回栈协同调度等等知识点。

王三的专栏 8425

Android 探究View onAttachedToWindow 触发时机

我们先从 的 说起。会调用当前 的 通过递归调用,会逐级调用 parent 的 ,最终会走到 的 因为 的 parent 是 ,所以最终会走调用 后续会执行 精简代码如下: 调用 方法,从逻辑中我们发现 host 其实就是 。所以就相当于 因为 也是一个 ViewGroup ,并且没有覆写 方法。所以我们直接看 的 方法 的 方法 ,遍历 子view , 然后调用 。发现 的 会调用 。到此 , 已经分析完。...........................

赵彦军 5219

Android View 生命周期

回顾 Activity 生命周期6个登录后复制 onCreate —— onStart 可见 —— onResume 有焦点 —— onPause 无焦点 —— onStop 不可见 —— onDestory1.View 生命周期登录后复制 //默认 visibility = VISIBLE onFinishInfl...

weixin_30649185的博客 237

android activity view 获取高度,Android 开发 Activity里获取View的宽度高度 转载

前言:可能很多情况下,我们都会有在activity中获取view 的尺寸大小(宽度高度)的需求。面对这种情况,很多同学立马反应:这么简单的问题,还用你说?你是不是傻。。然后立马写下getWidth()、getHeight()等方法,洋洋得意的就走了。然而事实就是这样的吗?实践证明,我们这样是获取不到View的宽度高度大小的,可能很多同学又会纳闷了,这是为什么呢?一直不都是这样获取大小的嘛!疑问...

weixin_36369656的博客 392

Activity生命周期详解

原文出处链接:https://blog.csdn.net/qq_36270361/article/details/107141162 版权声明:本文为CSDN博主「Steven Jon」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。 原文链接:https://blog.csdn.net/qq_36270361/article/details/107141162 本文纯属复习下Activity生命周期知识,望大家细看,如有侵权,请联系我删除。 Activity Ac

~~代码中的南城故事,南城故事里的中分女王。 2024

Android16 默认第三方Launcher为主桌面

【代码】Android16 默认第三方Launcher为主桌面。

qq_19447521的博客 35

Android ANR实战排查:主线程SystemClock.sleep导致页面启动偶现无响应

🔍 ANR问题全链路解决方案 摘要:本文系统讲解Android ANR问题的全链路解决方案。首先指出单纯依赖Logcat无法定位根因的局限,详细介绍了两种ANR日志抓取方法:adb pull /data/anr/(适合开发板)dumpsys dropbox(适合商用手机)。通过真实案例堆栈分析,揭示了主线程调用第三方SDK同步方法导致SystemClock.sleep()阻塞的根因,并强调该问题偶现性特征。最后提出分层解决方案:应用层采用协程异步初始化,或SDK层改造为异步回调模式,并列出了五大开发避坑

知道的越多,不知道的越多。 375

手机远程控制电脑全平台横测:iOS安卓鸿蒙谁更强

一、手机控电脑,到底有多刚需?你可能也经历过这些场景:下班刚到家,老板打电话说有个紧急数据需要从公司电脑里拉出来周末在外面逛街,突然想起家里电脑上的渲染任务还没点"开始"出差在高铁上,只能用手机远程登上工作电脑改一个配置父母打电话说电脑出了奇怪的问题,你人在千里之外干着急这些时刻,不再是"可选项",而是"救命稻草"。但市面上的远程控制 App 一个比一个能吹——“高清流畅”、“低延迟”、“一键连接”。真用起来呢?画质糊成马赛克、触控操作反人类、键盘输入比手写还慢……到底哪一款才是真正好用的。

2401_89864609的博客 305

Android 新闻资讯客户端实战:从零搭建一个完整的新闻 App

在移动互联网时代,新闻资讯类 App 是最常见的应用场景之一。OkHttp 网络请求封装(GET / POST / PUT / DELETE / 文件上传)ViewPager + TabLayout + Fragment 的经典 Tab 分页模式Gson JSON 数据解析 JavaBean 映射Glide 图片加载框架的使用SQLite 本地数据库持久化SharedPreferences 登录态管理。

mmsx990的博客 260

第一个安卓程序

本文简要介绍如何使用Android Studio创建第一个安卓HelloWorld程序:1)新建EmptyViewActivity项目并命名;2)定位到layout目录下的activity_main.xml文件;3)配置虚拟设备(需提前下载系统镜像);4)运行程序。通过这四步即可完成基础安卓应用的创建测试。全文以操作流程为导向,适合初学者快速入门。(98字)

UE星空 177

Android录屏内部音频录制完全指南:原理、限制方案选型

本文解析了安卓录屏无声问题的根源解决方案。核心要点包括: 1)安卓10+才支持内部音频捕获,低版本系统无法实现; 2)音频来源分内部音频、麦克风静音三种模式; 3)部分应用会禁止音频捕获进行版权保护; 4)给出参数设置建议方案选型(系统自带、第三方工具、电脑投屏),推荐快录屏APP; 5)提供6步排查清单。文章指出多数情况是系统限制或配置问题,帮助用户针对性解决录屏无声问题。

365

保姆级智能座舱测试入门:从 Android Automotive OS 到 SOA 服务的 7 层验证

本文介绍了智能座舱的7层测试体系,从底层OS到顶层用户体验全覆盖验证。随着智能座舱复杂度提升,传统手工测试已无法满足需求。7个层级包括:OS内核层(L1)、硬件抽象层(L2)、框架层(L3)、应用层(L4)、SOA服务层(L5)、HMI/UX层(L6)性能层(L7)。每层详述了测试目标、核心测试项及工具链,如LTP、VTS、CTS、CANoe等。

XiuSLjie的博客 247

【阅读源码-Android】动画之Choreographer-2

注册 存储 调度 执行 回收│ │ │ │ │▼ ▼ ▼ ▼ ▼│ │ │ ││ │ → 直接请求 │ DueLocked │ ├─ token=null│ │ │ │ └─ 放回 mCallbackPool│ Locked │▼ ▼(按 dueTime 排序)单 Vsync 请求确保一帧只请求一次 vsync,避免重复 IPC对象池复用通过复用,避免高频分配导致的 GC 压力异步消息:所有帧相关消息都设为 asynchronous,避免被同步屏障阻挡两级 Jitter 修正。

凉水的博客 345

Qt 国产嵌入式操作系统实现文字转语音功能(ekho库)

Qt 国产嵌入式操作系统实现文字转语音功能(TTS)_tts驱动 转文字-CSDN博客在继上篇文章之后,甲方粑粑不满意使用eSpeak发出的声音太难听了,这就不得不找个替代品,声音稍微好听了一些。使用ekho开源库。Ekho(余音)是一个免费、开源的中文语音合成软件。它目前支持粤语、普通话(国语)、诏安客语、藏语、雅言(中国古代通用语)韩语(试验中),英文则通过Festival间接实现。Ekho支持Linux、WindowsAndroid平台。

希望能帮助大家,希望大家多多支持,你们的支持是我前进的动力。 2697

履带式搜救机器人机械结构设计.zip机械设计毕业设计

履带式搜救机器人机械结构设计.zip机械设计毕业设计

上一篇: git clean用法
下一篇: Android开发 org.gradle.api.plugins.UnknownPluginException: Plugin [xxx] was not found in any of the fo...
Thy拾
博客等级 码龄8年 26粉丝 293原创
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值