navigationevent
| 最近更新时间 | 稳定版 | 候选版 | Beta 版 | Alpha 版 | 
|---|---|---|---|---|
| 2025 年 10 月 8 日 | - | - | 1.0.0-beta01 | - | 
声明依赖项
如需添加 navigationevent 的依赖项,您必须将 Google Maven 制品库添加到项目中。如需了解详情,请参阅 Google 的 Maven 代码库。
在应用或模块的 build.gradle 文件中添加所需工件的依赖项:
Groovy
dependencies { implementation "androidx.navigationevent:navigationevent:1.0.0-beta01" }
Kotlin
dependencies { implementation("androidx.navigationevent:navigationevent:1.0.0-beta01") }
如需详细了解依赖项,请参阅添加 build 依赖项。
反馈
您的反馈将帮助我们改进 Jetpack。如果您发现了新问题,或对此库有任何改进建议,请告诉我们。创建新问题前,请先查看此库中的现有问题。您可以点击星标按钮,为现有问题投票。
如需了解详情,请参阅问题跟踪器文档。
此工件没有版本说明。
版本 1.0
版本 1.0.0-beta01
2025 年 10 月 8 日
发布了 androidx.navigationevent:navigationevent-*:1.0.0-beta01。版本 1.0.0-beta01 中包含这些提交内容。
API 变更
- 更正了 NavigationEvent.touchX和NavigationEvent.touchY的FloatRange注释。这些值表示绝对像素坐标,没有1.0上限。(I4b205、b/445989313)
- 将 NavigationEventDispatcherOwner可组合项重构为rememberNavigationEventDispatcherOwner。该函数现在直接返回NavigationEventDispatcherOwner。如需将此所有者提供给子组合,请使用CompositionLocalProvider。(I874b2、b/444446629)
版本 1.0.0-alpha09
2025 年 9 月 24 日
发布了 androidx.navigationevent:navigationevent-*:1.0.0-alpha09。版本 1.0.0-alpha09 中包含这些提交内容。
API 变更
- 直接使用 NavigationEventTransitionState.Idle单例对象,而不是实例化Idle()。(Ic7d9e、b/444734264)
- 将便捷构造函数设为内部函数;通过公共 NavigationEventDispatcher.history获取实例,而不是直接构造。(I3b7e0、b/444734264)
- 需要通过 rememberNavigationEventState创建NavigationEventState;构造函数现在是内部函数。(Ie143c、b/444734264)
- 采用 onBackCompletedFallback,替换fallbackOnBackPressed用法和构造函数参数。行为未发生变化;仅在已完成且未处理的返回事件上调用。(Idabe9、b/444734264)
- NavigationEventHistory(mergedHistory, currentIndex)的主要构造函数现在为- internal。外部使用者必须使用公共构造函数(空构造函数或基于分区的构造函数)来创建实例。(I1c047、b/444734264)
- 使 View.setViewTreeNavigationEventDispatcherOwner接受可为 null 的所有者(Ic9eb6、b/444436762)
- NavigationEventInfo现在是- abstract class,而不是- interface。更新所有自定义实现,使其继承自该类(例如- data class MyInfo : NavigationEventInfo())。(I1e59c、b/444734264)
- 移除了旧版 NavigationEventDispatcher.state属性和getState<T>()函数。使用新的单独的dispatcher.transitionState(用于手势进度)和dispatcher.history(用于导航堆栈)流程。(Ic2ceb、b/444734264)
- 替换了 NavigationEventInput.onInfoChanged(...)回调。实现新的onHistoryChanged(history: NavigationEventHistory)回调,以单个NavigationEventHistory对象的形式接收更新。(I23e0b、b/444734264)
- 推出新的全局 NavigationEventDispatcher.historyStateFlow。此非泛型流程允许观察者仅订阅导航堆栈的更改,并在手势进度期间保持稳定。这是transitionState的对应项。(I1db10、b/444734264)
- 推出新的全局 NavigationEventDispatcher.transitionStateStateFlow。此非泛型流程允许观测者仅订阅物理手势状态(空闲/进行中),与历史记录分开。(I171fa、b/444734264)
- 介绍 NavigationEventHistoryState类。这将作为用于观察导航信息历史记录(与手势状态分开)的核心 API。(I81ca5、b/444734264)
- NavigationEvent现在标记为- @Immutable,从而允许 Compose 编译器优化重新组合。(If78c7、b/444734264)
- 更新了 navigationevent-compose处理程序 API。NavigationEventHandler和NavigationBackHandler(以及变体)现在支持接受提升的NavigationEventState的新重载。简单的重载(采用currentInfo)已保留,现在在内部使用此新状态模型。(Ic3251、b/444734264)
- 将新的 @StableNavigationEventState<T>状态持有者添加到navigationevent-compose库。此对象将本地历史记录与本地手势状态相结合,是rememberNavigationEventState和NavigationEventHandler之间的主要链接。(Ifb69f、b/444734264)
- 向 NavigationEventHandler添加了一个新的公共只读transitionState: TransitionState属性。处理程序现在可以维护自己的过渡状态,外部系统可以观察到该状态。(I9acd2、b/444734264)
- 引入新的 TransitionState密封类。这将作为用于观察手势状态的核心 API,与导航历史记录分开。(Id4beb、b/444734264)
- 将 currentInfo、backInfo和forwardInfo作为NavigationEventHandler上的公共只读属性公开。(Ia7636、b/444734264)
- NavigationEventHandler的实现现在必须向基本构造函数提供- initialInfo: T值。(Idcfea、b/444734264)
- 将 OnBackInvokedInput替换为OnBackInvokedOverlayInput或OnBackInvokedDefaultInput。(I5323f、b/428948766)
- 将 NavigationEventState标记为@Immutable。这可确保观察此状态的可组合项能够正确跳过重组,从而提高 Compose 性能。(I399c8)
- 将 NavigationEventInfo.NotProvided重命名为NavigationEventInfo.None;,并更新引用。不会带来任何行为上的变化。(I5e2d4)
- NavigationEventInfo现在标记为- @Immutable,从而允许 Compose 编译器优化重新组合。(I7c112)
- 通过有趣的界面改进了 Java 人体工程学,以实现后退完成回退。(I8a860)
- 已将 onHasEnabledHandlerChanged重命名为onHasEnabledHandlersChanged。这明确指出,回调报告的是所有处理程序的集体启用状态,而不仅仅是一个处理程序的启用状态。(I1af61、b/443711297)
- 从 NavigationEventDispatcher;中移除了hasEnabledHandler(),请改用NavigationEventInput.onHasEnabledHandlersChanged。(Idef72、b/443711297)
- 向 NavigationEventInput添加了onInfoChanged回调,以将导航历史记录的更改通知给监听器。这会提供当前堆栈、后退堆栈和前进堆栈的完整上下文,使输入能够对上下文信息做出反应。(I69a8b、b/443282983)
- 将 NavigationEvent的swipeEdge设为@IntDef(Icee54、b/443950342)
- 向 NavigationEventDispatcher.addInput添加priority参数,以将调度程序的作用域限定为一个优先级;现在,只有当该优先级的回调发生变化时,才会触发onHasEnabledCallbacksChanged等事件。(I3e488、b/443711297)
- 为清楚起见,将 NavigationEventDispatcher实参从parentDispatcher重命名为 parent。(Id4f1f、b/443801782)
- 移除了 NavigationEventPriority,改用@IntDef(面向 Java 用户)(I10a9f、b/440514265)
- 强制执行导航处理程序合约。如果您的 NavigationEventHandler将isBackEnabled或isForwardEnabled设置为true,您现在必须分别替换onBackCompleted或onForwardCompleted。默认实现现在会抛出异常,以防止出现无提示失败。(I17c62)
- 在添加导航事件处理程序时,强制执行有效的优先级值。现在,如果使用不受支持的优先级调用 addHandler,系统会抛出IllegalArgumentException,从而在所有目标平台上针对不正确的用法提供即时反馈。(I3c474)
bug 修复
- 使 addHandler具有幂等性;忽略重复注册。(I052aa、b/444734264)
- 在重组期间保持 NavigationEventState属性同步。(Ib3b4d、b/444734264)
- 确保 NavigationEventInputs在注册后立即收到当前上下文信息(当前、返回、前进)。(Ie65bf、b/443282983)
版本 1.0.0-alpha08
2025 年 9 月 10 日
发布了 androidx.navigationevent:navigationevent-*:1.0.0-alpha08。版本 1.0.0-alpha08 中包含这些提交内容。
新功能
- 引入基于 lambda 的 NavigationEventHandlerAPI,以替换基于 Flow 的处理程序。使用简单的回调处理向后和向前手势,而不是收集流,从而减少样板代码并避免取消问题。提供NavigationBackHandler和NavigationForwardHandler作为有针对性的便捷 API。移除基于 Flow 的NavigationEventHandler;迁移到新的回调。(I23bac、b/436248277)
- 允许被动监听器通过组合的返回信息访问完整的导航返回堆栈。使界面能够呈现预览和嵌套的导航历史记录,而不是仅限于最顶层的回调。(I7a510、b/436248277)
- 引入了明确的后退/当前/前进模型,以明确导航状态并支持使用嵌套处理程序进行前进导航。(Ib86da、b/420443609)
- 向 NavigationEventCallback添加了onForward*方法和isForwardEnabled。(Ic100f、b/436248290)
- 向 NavigationEventInput添加了前进导航支持。(I5734b)
API 变更
- 使用 TestNavigationEventCallback启用对前进导航事件的测试。使用isForwardEnabled和onForward*钩子。(I21fb5、b/420443609)
- 将 NavEvent中的onEvent*回调重命名为onBack*。(I228b3、b/436248290)
- 将 SwipeEdge转换为内联类。(Id5e01)
- 使 navigationevent库可与 Java 互操作。现在,所有公共 API 都可以从 Java 代码中完全访问,从而可以无缝集成到混合语言项目或仅使用 Java 的项目中。(Ibc944、I5465f、I9fb1e、b/440532890b/443040294)
- 通过将 NavigationEventCallback重命名为NavigationEventHandler来明确 API 角色。此更改更好地反映了该类处理多阶段导航手势的用途。相应的addCallback方法现在是addHandler。(I2492a、b/443040331)
bug 修复
- 防止在向前导航时运行后退回退。(I74814、b/436248290)
- 添加对预测性前进导航的支持。NavigationEventAPI 现在可以处理向后和向前手势,从而为这两个导航方向实现一致的动画。(Idc98c、b/436248290)
- 防止在移除子 NavigationEventDispatcherOwner时发生重组期间的IllegalStateException崩溃。(Iff50c、b/412629020)
- 被动监听器现在可以通过组合返回信息访问完整的返回堆栈,从而使界面能够呈现预览和嵌套的导航历史记录,而不仅仅限于最顶层的回调。(I7a510、b/436248277)
版本 1.0.0-alpha07
2025 年 8 月 27 日
发布了 androidx.navigationevent:navigationevent-*:1.0.0-alpha07。版本 1.0.0-alpha07 中包含这些提交内容。
API 变更
- 移除了 NavigationEventDispatcher.onHasEnabledCallbacksChanged。(I50e97)
- 将 NavigationEventCallback.onEventCompleted()设为抽象。(I36b38)
- 将 NavigationEventCallback#on*方法更改为protected。更新调用代码以替换它们。(I6b691)
- 重命名 DirectNavigationEventInput函数。(Iffb62)
- 已将 NavigationEventInput.onAttach重命名为onAdded。(I2d0b8)
- 已将 NavigationEventInput.onDetach重命名为onRemoved。(I2d0b8)
- 已将 NavigationEventInputHandler重命名为NavigationEventInput。(I676a4)
- 在 NavigationEventInput.onHasEnabledCallbacksChanged中添加了@EmptySuper。(If9853)
- 在 NavigationEventInputHandler中实现onAttach。(I03648)
- 在 NavigationEventInputHandler中实现onDetach。(I03648)
- 默认情况下,在创建时将 NavigationEventCallback设置为启用。(Ic0188)
- 将 NavigationEventInput.addOnHasEnabledCallbacksChangedCallback替换为NavigationEventInput.onHasEnabledCallbacksChanged。(I64e93)
- 要求 NavigationEventDispatcher.addInput使用主线程。(Ic2930)
- 要求 NavigationEventDispatcher.removeInput使用主线程。(Ic2930)
- 移除了 Dispatcher.addOnHasEnabledCallbacksChangedCallback。替换成了Dispatcher.onHasEnabledCallbacksChanged。(Ida3e3、b/436530096)
bug 修复
- 修复了以下 bug:添加已附加的处理程序或移除未附加的处理程序会触发不正确的生命周期逻辑。(I9e47b)
版本 1.0.0-alpha06
2025 年 8 月 13 日
发布了 androidx.navigationevent:navigationevent-*:1.0.0-alpha06。版本 1.0.0-alpha06 中包含这些提交内容。
新功能
被动监听器 API
现在,您可以从任何导航宿主传递自定义情境信息,并从界面中的任何位置被动监听手势状态变化。这样,系统便可为预测性返回和其他手势驱动的导航启用情境感知动画。
此功能包含两部分:
- 提供信息 - 使用 NavigationEventInfo携带自定义数据。
- 消耗状态 - 使用 dispatcher.state(NavigationEventState) 观察手势进度和上下文。
- NavigationEventCallback现在公开了- setInfo(currentInfo, previousInfo)方法,以便通过一次调用设置手势上下文(I1d5e7、b/424470518)。
- NavigationEventHandler添加了一个接受- currentInfo和- previousInfo的新重载,使其成为在 Compose 应用中提供上下文的主要 API(I6ecd3、b/424470518)。
示例:
  data class MyScreenInfo(val screenName: String) : NavigationEventInfo
  NavigationEventHandler(
      enabled = true,
      currentInfo = MyScreenInfo("Details Screen"),
      previousInfo = MyScreenInfo("Home Screen")
  ) { /* Handle back completion */ }
- NavigationEventDispatcher现在会公开- dispatcher.state和- dispatcher.getState<T>()(If7fae、Ia90ca、b/424470518)。借助这些基于- StateFlow的 API,任何界面都可以观察手势进度和情境数据,而无需直接处理事件。
示例:
  val gestureState by LocalNavigationEventDispatcherOwner.current!!
      .navigationEventDispatcher
      .state
      .collectAsState()
  val progress = gestureState.progress // Returns latestEvent.progress or 0F
  when (val state = gestureState) {
      is InProgress -> {
          val toScreen = state.currentInfo as MyScreenInfo
          val fromScreen = state.previousInfo as MyScreenInfo
          println("Navigating from ${fromScreen.screenName} to ${toScreen.screenName}")
      }
      is Idle -> { /* Idle state */ }
  }
- 向 - NavigationEventState(I7b196) 添加了- progress属性,该属性在进行中时返回- latestEvent.progress,否则返回- 0F:- val progress = state.progress
- 添加了 - NavigationEventDispatcherOwner可组合项,用于以分层方式创建、关联和处置- NavigationEventDispatcher实例。支持动态控制调度程序的启用状态和自动清理。- @Composable fun Sample() { NavigationEventDispatcherOwner(enabled = true) { val localDispatcherOwner = LocalNavigationEventDispatcherOwner.current } }
API 变更
- isPassthrough参数已从- NavigationEventCallback中移除。(I99028、b/424470518)
- NavigationEventState构造函数现在是内部函数。对于测试,请通过- DirectNavigationEventInputHandler更新状态(默认为- Idle)。调用- handleOnStarted或- handleOnProgressed可将状态设置为- InProgress,调用- handleOnCompleted或- handleOnCancelled可将状态返回到- Idle。如需更新- NavigationEventInfo,请使用- NavigationEventCallback.setInfo。(I93dca、b/424470518)
- 向 NavigationEvent添加了默认参数,以便更轻松地进行实例化并简化测试,该函数应取代TestNavigationEvent使用。(I5dc49、I232f4)
- 添加了 TestNavigationEventCallback,用于测试具有特定当前/之前状态的导航事件。(Idd22e、b/424470518)
- NavigationEventInputHandler已更改为抽象类,以替换之前的- AbstractNavigationEventInputHandler,并在- DirectNavigationEventInputHandler中实现(Iadde5、Ifed40I3897c、b/432616296、b/435416924)
- NavigationEventInputHandler中的- send*函数已将其前缀重命名为- handle*。(Iffcaf)
- OnBackInvokedInputHandler现在扩展了新近- abstract的- NavigationInputHandler。(Ib45aa)
- 更改了 NavigationEventDispatcherOwner,要求使用父调度程序,您必须明确传递null才能创建根调度程序。(Ia6f64、b/431534103)
bug 修复
- 通过避免在 NavigationEventDispatcher.dispose()中复制集合来提高效率。(I4ab09)
- 修复了 NavigationEventHandler未正确响应其启用状态变化的问题。(Ia5268、I19bec、I5be5c、b/431534103)
Google 文档更新
- 扩展了 NavigationEvent的 KDoc,以阐明其作为统一事件封装容器的角色,并详细说明了不同导航类型(手势、点击)的属性行为。(I91e8d)
- 更新了有关系统返回处理 Compose API(BackHandler、PredictiveBackHandler、NavigationEventHandler)的文档,以明确说明与回调顺序相关的行为。(I7ab94,)
依赖项更新
- NavigationEvent现在依赖于 Compose Runtime 1.9.0-beta03,这使得- navigationevent-compose制品能够支持所有 KMP 目标。(Ia1b87)
版本 1.0.0-alpha05
2025 年 7 月 30 日
发布了 androidx.navigationevent:navigationevent-*:1.0.0-alpha05。版本 1.0.0-alpha05 中包含这些提交内容。
父子层次结构支持:
NavigationEventDispatcher 现在可以有父调度器和子调度器,从而形成分层树结构。这样一来,导航事件就可以通过链式调度程序反映界面结构层次结构,从而在复杂的 Compose 界面组件中更灵活地传播和管理。(I194ac)
  // Create a parent dispatcher that will manage navigation events at a higher level.
  val parentDispatcher = NavigationEventDispatcher()
  // Create a child dispatcher linked to the parent, forming a hierarchy.
  val childDispatcher = NavigationEventDispatcher(parentDispatcher)
分层 isEnabled 属性可实现对调度程序的自上而下的控制。当调度器上的 isEnabled 设置为 false 时,它会自动停用其所有后代调度器。此功能可高效地关闭导航事件系统的整个分支。(I9e985)
  // Disabling the child dispatcher disables all its callbacks and any of its children recursively.
  childDispatcher.isEnabled = false
此外,NavigationEventCallback 上的 isEnabled 属性现在会考虑其关联的调度器的启用状态。这意味着,只有当回调本身及其调度程序(包括其祖先)均处于启用状态时,回调才会被视为已启用,从而确保对回调激活进行一致的分层控制。(I1799a)
  // Create a test callback and add it to the child dispatcher.
  val callback1 = TestNavigationEventCallback(isEnabled = true)
  childDispatcher.addCallback(callback1)
  // Since the childDispatcher is disabled, the callback is effectively disabled as well.
  assertThat(callback1.isEnabled).isFalse()
引入了新的 dispose() 方法,用于正确清理调度程序及其子级。调用 dispose() 会停止监听器以防止内存泄漏,以递归方式处置所有子调度器,移除注册到调度器的所有回调,并将其从父级取消关联。这样可确保在不再需要调度程序时正确释放资源。(I9e985)
  // Dispose the child dispatcher to clean up resources.
  childDispatcher.dispose()
如果对已处置的调度程序调用任何公共方法,系统会立即抛出 IllegalStateException。这样可以防止出现无提示失败,并帮助开发者在开发期间发现不当使用情况。(Ic2dc3)
  val callback2 = TestNavigationEventCallback()
  // Attempting to use a disposed dispatcher will throw an exception.
  assertThrows<IllegalStateException> {
      childDispatcher.addCallback(callback2)
  }
注意:我们将在 aosp/3692572 中引入一个新的 NavigationEventDispatcherOwner 可组合项,用于自动管理 Compose 界面中的子调度程序。不过,此更改未纳入当前版本,计划在下一个版本中纳入。
导航测试库
- 添加了 navigationevent-testing模块,以便为navigationevent库提供专用测试实用程序。(0e50b6)
- 添加了用于测试的 TestNavigationEventCallback伪实用程序类。它会记录回调方法调用并存储收到的NavigationEvent项,以支持验证。(4a0246)
- 添加了 TestNavigationEvent伪实用程序函数,用于创建具有默认值的NavigationEvent实例,从而简化导航事件处理的单元测试。(3b63f5)
- 添加了用于测试的 TestNavigationEventDispatcherOwner伪实用程序类。它会跟踪回退和启用状态更改事件计数,以支持测试中的互动验证。(c8753e)
API 变更
- 将 NavigationEventInputHandler从androidMain移至commonMain,以便在 KMP 通用代码中使用。添加了用于调度事件的新public send*方法。将NavigationEventDispatcher上派发函数的public更改为internal;用户现在必须使用NavigationEventInputHandler来发送事件。(Ia7114)
- 已将 NavigationInputHandler重命名为OnBackInvokedInputHandler。(I63405)
bug 修复
- 重构了 NavigationEventDispatcher,通过避免中间列表分配和提高回调调度性能来减少开销。(I82702、I1a9d9)
- 向 NavigationEvent中的touchX、touchY和progress字段添加了@FloatRange注释,以在编译时强制执行有效的值范围并提高 API 安全性。(Iac0ec)
版本 1.0.0-alpha04
2025 年 7 月 2 日
发布了 androidx.navigationevent:navigationevent-*:1.0.0-alpha04。版本 1.0.0-alpha04 中包含这些提交内容。
bug 修复
- 使用 implementedInJetBrainsFork将navigationevent-compose添加到commonStubs目标,以符合 Compose 惯例。JetBrains 提出的更改。(f60c79)
- 修复了将 Compose 编译器插件应用于 Kotlin/Native 的问题,以确保正确生成桩。对公开 API 或行为没有影响。(1890c9)
版本 1.0.0-alpha03
2025 年 6 月 18 日
发布了 androidx.navigationevent:navigationevent-*:1.0.0-alpha03。版本 1.0.0-alpha03 中包含这些提交内容。
新功能
- 引入了新的 navigationevent-compose模块,以支持navigationevent库中的 Jetpack Compose 功能。(980d78)
- NavigationEventCompose 添加了新的- LocalNavigationEventDispatcherOwner本地组合。它会返回可为 null 的值,以更好地确定其在当前组合中是否可用。现在,如果未找到底层所有者,- NavigationEventHandler会抛出错误。(62ffda)
- NavigationEventCompose 添加了一个新的- NavigationEventHandler可组合项来处理(预测性返回手势)事件。它提供了一个- Flow,其中包含您提供的挂起 lambda 中必须收集的- NavigationEvent对象 c42ba6:
NavigationEventHandler { progress: Flow<NavigationEvent> ->
  // This block is executed when the back gesture begins.
  try {
    progress.collect { backEvent ->
      // Handle gesture progress updates here.
    }
    // This block is executed if the gesture completes successfully.
  } catch (e: CancellationException) {
    // This block is executed if the gesture is cancelled
    throw e
  } finally {
    // This block is executed either the gesture is completed or cancelled
  }
}
API 变更
- 现在,每个 NavigationEventCallback一次只能注册一个NavigationEventDispatcher;如果将其添加到多个调度程序,则会抛出IllegalStateException。请注意,此行为与允许使用多个调度程序的OnBackPressedDispatcher不同。(e82c19)
- 将 isPassThrough设为val,以防止在导航期间发生突变,从而避免破坏NavigationEvent的调度。(I0b287)
版本 1.0.0-alpha02
2025 年 6 月 4 日
发布了 androidx.navigationevent:navigationevent-*:1.0.0-alpha02。版本 1.0.0-alpha02 中包含这些提交内容。
API 变更
- 将 NavigationEventDispatcher的次构造函数替换为具有默认实参的构造函数。(I716a0)
- 从 NavigationEventCallback中移除了优先级属性。请改为将优先级传递给NavigationEventDispatcher.addCallback()。(I13cae)
bug 修复
- 修复了在调用 NavigationEventCallback.remove()时可能因同时修改可关闭对象的内部列表而发生的ConcurrentModificationException。(b/420919815)
版本 1.0.0-alpha01
2025 年 5 月 20 日
发布了 androidx.navigationevent:navigationevent-*:1.0.0-alpha01。版本 1.0.0-alpha01 中包含这些提交内容。
新功能
- androidx.navigationevent库提供了一个 KMP-first API,用于处理系统返回以及预测性返回。- NavigationEventDispatcher用作注册一个或多个- NavigationEventCallback实例以接收系统返回事件的通用 API。
- 此层位于 androidx.activity中之前发布的 API 之下,旨在成为一种更灵活的替代方案,用于在更高级别的组件中使用 Activity API 或直接使用 Android 框架OnBackInvokedDispatcherAPI。androidx.activityAPI 已在 Navigation Event API 的基础上重写,作为 Activity 1.12.0-alpha01 的一部分。
