Android 探究View onAttachedToWindow 触发时机
转载请标明出处:http://blog.csdn.net/zhaoyanjun6/article/details/125607542
本文出自【赵彦军的博客】
生命周期观察
Activity
class MainActivity : AppCompatActivity() {
private lateinit var binding: ActivityMainBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
Log.d("yu--", "Activity onCreate")
}
override fun onResume() {
super.onResume()
Log.d("yu--", "Activity onResume")
}
override fun onAttachedToWindow() {
super.onAttachedToWindow()
Log.d("yu--", "Activity onAttachedToWindow")
}
override fun onPause() {
super.onPause()
Log.d("yu--", "Activity onPause")
}
override fun onStop() {
super.onStop()
Log.d("yu--", "Activity onStop")
}
override fun onDestroy() {
super.onDestroy()
Log.d("yu--", "Activity onDestroy")
}
override fun onDetachedFromWindow() {
super.onDetachedFromWindow()
Log.d("yu--", "Activity onDetachedFromWindow")
}
}
MyView
public class MyView extends View {
public MyView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
}
@Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
}
@Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
}
}
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<com.example.myapplication.MyView
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</FrameLayout>
生命周期回调:
D/yu--: Activity onCreate
D/yu--: Activity onResume
D/yu--: Activity onAttachedToWindow
D/yu--: View onAttachedToWindow
D/yu--: Activity onPause
D/yu--: Activity onStop
D/yu--: Activity onDestroy
D/yu--: View onDetachedFromWindow
D/yu--: Activity onDetachedFromWindow
从回调的结果来看:
- 1、Activity onResume 之后回调 onAttachedToWindow
- 2、Activity onDestroy 之后回调 onDetachedFromWindow
- 3、Activity 的 onAttachedToWindow 回调之后,才会回调 view 的 onAttachedToWindow
- 4、View onDetachedFromWindow 回调之后,才会回调 Activity onDetachedFromWindow
源码探究
当 Activity
发生 resume
的时候,实际上是 ActivityThread
的 handleResumeActivity()
被调用。
performResumeActivity
方法,会执行 activity
的 onResume
方法。
WindowManagerImpl.java
这里的 mGlobal
就是 WindowManagerGlobal
类
我们看 WindowManagerGlobal
的 addView
方法
也就是说 , WindowManagerGlobal 的 addView 方法 ,创建了 ViewRootImpl , 然后建立 DecorView 和 ViewRootImpl 绑定关系。
回到正题,继续看 ViewRootImpl
的 requestLayout()
scheduleTraversals()
后续会执行 doTraversal();
精简代码如下:
调用 host.dispatchAttachedToWindow
方法,从逻辑中我们发现 host 其实就是 DecorView
。
所以就相当于 DecorView.dispatchAttachedToWindow
因为 DecorView
也是一个 ViewGroup ,并且没有覆写 dispatchAttachedToWindow
方法。
所以我们直接看 ViewGroup
的 dispatchAttachedToWindow
方法。
ViewGroup
的 dispatchAttachedToWindow
方法 ,首先会调用 super.dispatchAttachedToWindow
,实际上是回调当前 ViewGroup
的 onAttachedToWindow
。
然后遍历 子view , 然后调用 child.dispatchAttachedToWindow
。
发现 View
的 dispatchAttachedToWindow
会调用 onAttachedToWindow
。
到此 ,onAttachedToWindow
已经分析完。
当一个view 被 add 的时候
我们先从 ViewGroup
的 addView
说起。
会调用当前 ViewGroup
的 requestLayout()
通过递归调用,会逐级调用 parent 的 requestLayout()
,最终会走到 DecorView
的 requestLayout()
因为 DecorView
的 parent 是 ViewRootImpl
,所以最终会走ViewRootImpl
调用 requestLayout()
下面的逻辑,我们就不分析了,和上面分析的一致。
Activity onAttachedToWindow 是怎么触发的?
首先,我们来看看 Activity
的 onAttachedToWindow
长什么样子的?
Activity
实现了 Window.Callback
, 并且实现了 onAttachedToWindow
、 onDetachedFromWindow
代码如下:
看 Activity
的 attach
方法,调用了 mWindow.setCallback(this)
mWindow
是 PhoneWindow
, 看看 PhoneWindow
的 setCallback
到这里我们基本明白了,Activity
的 onAttachedToWindow
是什么。
剩下的,我们只要知道 window.mcallback
接口实例,在什么情况下会被调用,就能知道触发时机了。
看看 DecorView
的 onAttachedToWindow
的方法。
- 首先
DecorView
的onAttachedToWindow
会调用 - 然后
callback
的onAttachedToWindow
会被调用
这个 callback
是 在 Activity
中实现的的接口 , 所以 Activity
的 onAttachedToWindow
就会被调用
结论:
Activity
的onAttachedToWindow
在DecorView
的onAttachedToWindow
被调用时触发
OnAttachStateChangeListener
在 dispatchAttachedToWindow
的代码中,我们发现 除了 onAttachedToWindow
方法会执行外,OnAttachStateChangeListener
也会回调,mOnAttachStateChangeListeners
是一个集合,可以有多个 Listener
使用如下:
public class MyView extends View {
public MyView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
addOnAttachStateChangeListener(new OnAttachStateChangeListener() {
@Override
public void onViewAttachedToWindow(View v) {
}
@Override
public void onViewDetachedFromWindow(View v) {
}
});
}
}
在 onAttachedToWindow
能获取到 View 的宽高吗?
答案:不能,因为 onAttachedToWindow
在回调时,还没有 measure
, layout
当子view 被 add 的时候,会触发View
树上其他View
回调 onAttachedToWindow
吗?
答案:不会,只会触发当前子view 的 onAttachedToWindow
被回调,其他View 不会触发。
这篇好文章是转载于:学新通技术网
- 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
- 本站站名: 学新通技术网
- 本文地址: /boutique/detail/tanhgfahaa
-
photoshop保存的图片太大微信发不了怎么办
PHP中文网 06-15 -
Android 11 保存文件到外部存储,并分享文件
Luke 10-12 -
《学习通》视频自动暂停处理方法
HelloWorld317 07-05 -
word里面弄一个表格后上面的标题会跑到下面怎么办
PHP中文网 06-20 -
photoshop扩展功能面板显示灰色怎么办
PHP中文网 06-14 -
微信公众号没有声音提示怎么办
PHP中文网 03-31 -
excel下划线不显示怎么办
PHP中文网 06-23 -
excel打印预览压线压字怎么办
PHP中文网 06-22 -
怎样阻止微信小程序自动打开
PHP中文网 06-13 -
TikTok加速器哪个好免费的TK加速器推荐
TK小达人 10-01