企业如何通过vue小程序开发满足高效运营与合规性需求
1075
2022-11-19
Android 探究View onAttachedToWindow 触发时机
文章目录
生命周期观察源码探究当一个view 被 add 的时候Activity onAttachedToWindow 是怎么触发的?OnAttachStateChangeListener在 `onAttachedToWindow` 能获取到 View 的宽高吗?当子view 被 add 的时候,会触发`View`树上其他`View`回调 `onAttachedToWindow` 吗?
生命周期观察
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
生命周期回调:
D/yu--: Activity onCreateD/yu--: Activity onResumeD/yu--: Activity onAttachedToWindowD/yu--: View onAttachedToWindowD/yu--: Activity onPauseD/yu--: Activity onStopD/yu--: Activity onDestroyD/yu--: View onDetachedFromWindowD/yu--: Activity
从回调的结果来看:
1、Activity onResume 之后回调 onAttachedToWindow2、Activity onDestroy 之后回调 onDetachedFromWindow3、Activity 的 onAttachedToWindow 回调之后,才会回调 view 的 onAttachedToWindow4、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 不会触发。
版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。
发表评论
暂时没有评论,来抢沙发吧~