1.子线程更新UI全解
2.Android UI线ç¨
3.View 绘制流程源码分析
4.跑马灯带你深入浅出TextView的源码世界
子线程更新UI全解
子线程更新 UI 的问题在 Android 开发中至关重要。通常,尝试在子线程更新 UI 会导致应用崩溃,这是因为 Android 设计了一条铁律:禁止子线程直接操作 UI。原因在于,屏幕刷新率至少是卖卷源码每 ms 一次,要求 UI 更新快速响应以避免卡顿。如果在子线程中操作 UI,可能导致线程不安全,进而产生不可预知的 UI 结果。
深入理解这一限制,我们从源码层面分析。Android 版本的框架中,错误通常从 View#setBackgroundColor() 开始,层层传递至 ViewRootImpl#checkThread(),java看源码的经验这里会检查线程是否与预期一致,如果不一致则抛出异常。这个检查机制确保 UI 更新在主线程中进行,避免了多线程对 UI 的并发修改。
源码追踪显示,从 imageView.setBackgroundColor() 开始,调用链会到 View#requestLayout(),接着递归到 Activity 的顶层 View,通过 setContentView() 和 PhoneWindow 的设置,最终到达 DecorView,这是整个 View 树的根节点。DecorView 作为 ViewParent 的概念在此时显得重要,因为它虽然没有直接父 View,但仍有 ViewParent,巅峰qq代挂网源码即 ViewRootImpl。
ViewRootImpl 的 requestLayout() 方法再次执行线程检查,确保它是在主线程初始化的。如果试图在子线程更新 View,除非满足特定条件,如在 Activity 的 onResume() 之前更新,或者在非硬件加速且更新的是特定 View 的某些方法时,否则会触发异常。
总结来说,尽管存在绕过检查的可能,但遵循 Android 设计原则,最好避免在子线程更新 UI。因为这种做法可能带来不可预测的行为,尤其是寸土寸金指标源码在定制化系统中。了解了这些底层机制后,开发者应确保 UI 更新始终在主线程进行,以保证应用的稳定性和用户体验。
Android UI线ç¨
æèï¼å å¿ é¡»äºè§£ä¸é¢2个é®é¢
1.顾åæä¹ UIçº¿ç¨ å°±æ¯å·æ°UI æå¨çº¿ç¨
2.UIæ¯å线ç¨å·æ°
1.对Activity æ¥è¯´ UI线ç¨å°±æ¯å ¶ä¸»çº¿ç¨
2.对Viewæ¥è¯´ UI线ç¨å°±æ¯å建ViewRootImplæå¨ç线ç¨
å¯ä»¥éè¿ WindowManager å é¨ä¼å建ViewRootImpl对象
好äºï¼è¿å ¥ä¸»é¢ãæ们æ¥æ ¢æ ¢æå¼é¢çº±ã
æ们å¯ä»¥åå«ä»å 个æ¹é¢åå ¥
æ们å¯è½é½æ使ç¨è¿ runOnUiThread ç°å¨æ¥çççæºç å®ç°ã
å¯ä»¥ä»ä¸é¢çæºç çå°
ä¸æ¯UIçº¿ç¨ å°±ç¨Handleråå°Handleræå¨ç线ç¨ä¸ï¼å¦ææ¯UI线ç¨ç´æ¥å°±è°ç¨runæ¹æ³ã
Activityçå建ï¼
1.Activityå建ï¼mInstrumentation.newActivity
2.å建Context ï¼ContextImpl appContextcreateBaseContextForActivity(r)
æ们ç»å¸¸ç¨è¿ä¸ªæ¹æ³å¹²çäºæ å°±æ¯ï¼è¦ä¹å¨onCreateä¸è·åView宽é«çå¼ãè¦ä¹å°±æ¯å¨å线ç¨ä¸åä¸äºèæ¶æä½ ï¼ç¶åpoståå°å¯¹åºViewæå¨ççº¿ç¨ æ¥ç»å¶UIæä½ãé£ä¹è¿ä¸ªå¯¹åºç线ç¨å°±æ¯UI线ç¨äºã
é£ä¹è¿ä¸ªUI线ç¨å°±ä¸å®æ¯ä¸»çº¿ç¨åï¼
æ¥æ¥ç»§ç»æ¥çãå®çæºç View:post
mAttachInfo å¨dispatchAttachedToWindow ä¸è¢«èµå¼ ï¼ä¹å°±æ¯å¨ViewRootImplå建çæ¶åï¼æ以æ¯å建ViewRootImplæå¨ç线ç¨ã
attachInfo ä¸é¢æ¶å为null å¢ï¼å¨ViewRootImpl è¿æ²¡æ¥å¾åå建çæ¶åï¼ViewRootImpl å建æ¯å¨ âonResume" ä¹åãæä»¥å¨ Activity ç onCreate å»View.post é£ä¹AttachInfo æ¯ä¸ºnull ã
å½ AttachInfo == null é£ä¹ä¼è°ç¨ getRunQueue().post(action) ã
æç»è¿ä¸ªRunnable 被 ç¼åå° HandlerActionQueue ä¸ã
ç´å°ViewRootImpl ç performTraversals ä¸ è°ç¨dispatchAttachedToWindow(mAttachInfo, 0);ï¼ é£ä¹æä¼å»å¤ç RunQueue() ä¸çRunnableã
æ¥å¼ å¾ ä¾¿äºç解è¿ä¸ªæµç¨
æ们ææ¶åå»å线ç¨æä½UIçæ¶å(å¦ï¼requestLayout)ï¼ä¼å¾ç»å¸¸è§å°ä¸é¢ç æ¥éæ¥å¿ï¼
Only the original thread that created a view hierarchy can touch its views
为ä»ä¹ä¼æ¥è¿ä¸ªé误å¢ï¼
ç¿»è¯ä¸ä¸ï¼åªæå建è§å¾å±æ¬¡ç»æçåå§çº¿ç¨æè½æ¥è§¦å°å®çè§å¾ã
ä¹å°±æ¯æä½UIç线ç¨è¦åViewRootImplå建ç线ç¨æ¯åä¸ä¸ªçº¿ç¨æè¡ï¼å¹¶ä¸æ¯åªæ主线ç¨æè½æ´æ°UIåã
ViewRootImplå建ç线ç¨ï¼é£ä¹ ViewRootImpl å¨åªé被å建çå¢ï¼
ä»ä¸å¾å¯ä»¥çå°ViewRootImplå建æå¼å§æ¯ä» ActivityThread çHandleResumeActivityä¸å¼å§ ä¸ç´ ViewRootImpl å建ï¼ä¹å°±æ¯è¯´ViewRootImpl 对åºçUI线ç¨å ActivityThread å¨åä¸ä¸ªçº¿ç¨ ä¹å°±æ¯ä¸»çº¿ç¨ã
å¥½äº éè¿ä¸é¢ç讲解ï¼ä¸é¢çé®é¢ç¸ä¿¡ä½ å¯ä»¥èªå·±åçå¦~
View 绘制流程源码分析
在View的绘制流程中,ViewRootImpl的setView主流程涉及的关键步骤包括设置PFLAG_FORCE_LAYOUT和PFLAG_INVALIDATED。这一步骤在执行时,触发了View的重绘逻辑。
接下来,当View收到需要重绘的信号后,会执行invalidate方法。这个方法首先计算出需要重绘的dirty区域,然后从下向上,最终调用到ViewRootImpl的scheduleTraversals方法。这个过程中,vi编辑器源码脏区域的范围逐步扩大,直至整个View需要进行重绘。
在View的绘制流程中,PFLAG_FORCE_LAYOUT和PFLAG_INVALIDATED的使用至关重要。它们的设置触发了视图的重绘和布局过程,保证了UI在用户操作或其他事件触发时能够及时响应和更新。通过这种方式,系统确保了用户界面的实时性和交互性。
具体来说,当View收到布局或尺寸变化的信号时,会调用requestLayout方法,同时设置PFLAG_FORCE_LAYOUT标志。这个标志告诉系统,当前布局需要强制执行,即使布局尚未完成,也应立即进行更新。同时,invalidate方法的调用,会触发PFLAG_INVALIDATED标志的设置,表明视图需要重绘。
在ViewRootImpl中,scheduleTraversals方法是负责组织和执行视图层级中所有视图的重绘和布局的。它会根据脏区域和布局标志的设置,合理安排视图的更新顺序,确保系统的性能和用户体验。
总结整个流程,View的绘制和布局机制通过一系列的标志(如PFLAG_FORCE_LAYOUT和PFLAG_INVALIDATED)和方法(如requestLayout和invalidate)来协调和控制。这些机制使得系统能够高效地响应用户操作,实现流畅的UI交互。通过深入理解这些源码细节,开发者能够更好地优化UI性能,提高用户体验。
跑马灯带你深入浅出TextView的源码世界
本文将深入浅出地解析Android系统中TextView的跑马灯动画源码,以解决开发者在实际开发中遇到的问题。文章将通过一个具体问题作为出发点,引导读者从源码的角度分析和解决问题。 首先,面临的问题是Android 6.0及以上系统中点击“添加购物车”按钮时,TextView的跑马灯动画会出现跳动现象(动画重置,滚动从头开始)。面对这一现象,开发者往往需要从源码层面进行深入分析。 为了解决问题,文章建议采用以下步骤进行源码分析: 搜索“Android TextView 跑马灯原理”,找到关键代码实现,特别是与跑马灯启动相关的startMarquee()方法。 使用Android Studio搜索TextView并查看类接口图,找到startMarquee()方法的实现,对其进行初步分析。 确定找到的方法正确后,继续了解整个框架的实现流程,绘制主流程图。 接下来,文章将深入分析跑马灯动画的实现机制,包括TextView、Marquee内部类以及Choreographer系统。 在分析中,文章指出Choreographer是一个用于管理动画、输入和绘制的系统类,它通过监听DisplayEventReceiver来接收系统信号,并在每一帧中回调以确保动画的平滑性。在Choreographer中,Marquee会计算偏向值,然后触发TextView的刷新来实现动画效果。 文章进一步解析了Choreographer的实现原理以及Marquee在postFrameCallback中的具体操作,包括计算时间差、移动位移以及触发TextView刷新的过程。 最后,文章对问题进行了详细分析,揭示了导致跑马灯动画重置的根源在于“购物车”按钮的setText方法触发了requestLayout,从而导致了视图重绘。通过修改按钮的布局属性,问题得以解决。 总结而言,文章通过问题分析和源码解析,为开发者提供了一条清晰的路径,从现象出发,深入源码,最终找到问题的根本原因并解决,从而提升对Android系统内核的理解和应用能力。