android requestLayout等重绘分析

本文深入探讨了Android 4.4.2 KitKat版本中ViewRootImpl的scheduleTraversals()方法,讲解了如何触发和调度UI的重绘过程。当mTraversalRunnable未被post到mChoreographer时,系统会将其post并设置为Choreographer.CALLBACK_TRAVERSAL类型,此过程中可能涉及不同线程间的同步。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

基于4.4.2 kitkat source code

ViewRootImpl 中的scheduleTraversals()会先判断是否有  mTraversalRunnable 被post到   mChoreographer那里,如果没有,那么就post一个mTraversalRunnable(CALLBACK类型是Choreographer.CALLBACK_TRAVERSAL)到mChoreographer(和mhandler不一样的,可能不是同一个线程), 之前会试取获得mhandler的一个syncBarrier, 该

Barrier的作用是将之后所有仿如到handler的callback都阻塞住不让其执行,直到该barrier被释放为止, 而释放barrier则是在unscheduleTraversals()中做的,加barrier的用途应该是在保证重绘期间不会被别的事情干扰,在unscheduleTraversals()和doTraversal()调用的时候会被释放,

TraversalRunnable的run执行了 -> doTraversal() -> performTraversals() -> performDraw() -> draw() -> (如果当前正在执行
动画,那么就继续scheduleTraversals()以实现动态变化)

ViewRootImpl的requestLayout()在当前没有正在处理的layoutRequest时,就会scheduleTraversals(),中间会检查thread, 保证调用
此方法的thread和创建viewRootImpl的thread是同一个。

ViewRootImpl implements ViewParent (自己实现了自己的requestLayout方法来实现ViewParent接口)
ViewGroup extends View implements ViewParent, ViewManager (没有重写View的requestLayout方法,直接使用了)
View imp
<think>我们正在处理用户的问题:"我想在Android开发中,制对话框的界面 请问Android dialog redraw" 根据用户的问题,他想要制对话框的界面。在Android中,制视图通常是通过调用invalidate()或requestLayout()方法来实现的。但是,对于对话框,我们需要先获取对话框中的视图,然后对其进行操作。 步骤: 1. 获取对话框的窗口视图(Window的DecorView或者具体的内容视图)。 2. 调用invalidate()来整个视图,或者调用requestLayout()如果视图的尺寸或布局发生了变化。 但是,用户可能是在对话框显示后想要更新其内容。通常,我们不会直接整个对话框,而是更新对话框内的视图(如TextView、ImageView等),然后让这些视图自行。 另外,如果对话框是自定义的,我们可以通过自定义视图的引用来更新。 示例: 假设我们有一个自定义对话框,其中包含一个TextView,我们想更新这个TextView的文本并。 代码示例: ```java // 创建对话框 AlertDialog dialog = new AlertDialog.Builder(context) .setView(R.layout.custom_dialog) // 设置自定义布局 .create(); // 显示对话框 dialog.show(); // 获取自定义布局中的TextView TextView textView = dialog.findViewById(R.id.text_view); textView.setText("新的文本"); // 由于setText本身会触发,通常不需要额外调用invalidate。但如果需要,可以: textView.invalidate(); // 强制TextView // 或者如果布局变化了,调用requestLayout() // textView.requestLayout(); ``` 但是,如果用户想要完全制整个对话框(比如因为主题改变或者需要新应用样式),可能需要新创建对话框。因为对话框的窗口属性(如透明度、动画等)在显示后通常不能更改,需要新创建。 因此,根据需求,有两种情况: 情况1:更新对话框内的内容 -> 通过获取内部视图并更新,然后调用invalidate()(通常自动调用,但有时需要手动)。 情况2:新创建对话框(例如,在配置改变后)-> 关闭当前对话框,然后新创建并显示。 另外,注意:如果对话框是由Activity管理的,在Activity的onResume()中可能需要新显示对话框(如果配置改变导致Activity建,对话框不会自动恢复)。 根据引用[2]中提到的对话框样式,我们可以知道对话框的样式是在创建时设置的,显示后无法更改样式,所以如果需要更改样式,必须新创建对话框。 总结回答: 1. 如果只是更新对话框内容,获取视图并更新,然后调用invalidate()(如果需要)。 2. 如果需要更改对话框的样式或整体布局,则必须新创建对话框。 相关问题: 1. 如何在Android中更新对话框的内容? 2. 如何新创建对话框? 3. 在什么情况下需要新创建对话框而不是仅仅更新内容? 4. 如何优化对话框的制以避免性能问题?</think>在 Android 开发中制对话框界面,主要通过以下步骤实现: ### 1. **获取对话框的根视图** 对话框显示后,通过 `Window` 对象获取其根视图(通常是 `DecorView`): ```java View dialogView = dialog.getWindow().getDecorView(); ``` ### 2. **触发** - **局部更新**:仅内容区域(避免性能开销) ```java // 更新内容视图后 View contentView = dialog.findViewById(android.R.id.content); contentView.invalidate(); // 标记脏区域,触发onDraw() ``` - **全局**:强制整个对话框 ```java dialogView.invalidate(); // 整个对话框 // 或 dialogView.requestLayout(); // 若布局变化(如尺寸调整) ``` ### 3. **自定义对话框的主动** 如果是自定义对话框,在视图内部直接调用: ```java public class CustomDialog extends Dialog { private TextView mTextView; public void updateText(String newText) { mTextView.setText(newText); mTextView.invalidate(); // 更新后立即 } } ``` ### 4. **结合硬件加速优化** - 确保在 `AndroidManifest.xml` 中启用硬件加速: ```xml <application android:hardwareAccelerated="true" ... /> ``` - 避免在 `onDraw()` 中创建对象或执行耗时操作[^1]。 ### 关键注意事项 1. **`invalidate()` vs `requestLayout()`** - `invalidate()`:仅视图(内容变化时使用)。 - `requestLayout()`:新测量布局(尺寸/结构变化时使用)。 2. **性能优化** - 局部优先于全局。 - 使用 `View.postInvalidate()` 在非 UI 线程触发。 3. **样式刷新** 若需更新对话框样式(如背景/动画),必须建对话框: ```java dialog.dismiss(); Dialog newDialog = new Dialog(context, R.style.NewStyle); // 引用新样式[^2] newDialog.show(); ``` ### 示例场景 ```java // 动态改变对话框背景后 dialog.getWindow().setBackgroundDrawable(new ColorDrawable(Color.BLUE)); dialog.getWindow().getDecorView().invalidate(); ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值