片段管理器状态处理程序
重要
本文介绍的功能和指南为公共预览版,在正式发布之前可能会有重大修改。 Microsoft 不对此处提供的信息作任何明示或默示的担保。
FragmentManagerStateHandler
是可以在屏幕模式转换发生时帮助恢复片段的类。
将应用从双屏模式切换为单屏模式时,会重新创建所有片段,即使这些片段不可见。
使用该库时,只会重新创建需要的片段。
因为片段是从活动束中还原的,所以我们可以有两个在运行时根据分屏模式交换的束 - 一个束用于单屏模式,另一个束用于分屏模式。 这只能通过添加活动生命周期回调并在 onActivityPreCreated 回调中交换这两个束来实现。
组件将自动检测我们所处的屏幕模式,并且它将只恢复所需的片段,具体取决于屏幕模式。
重要
组件仅适用于 AndroidX 中的活动。
如何使用
class SampleApp : Application() {
override fun onCreate() {
super.onCreate()
FragmentManagerStateHandler.init(this)
}
}
class SampleActivity : AppCompatActivity() {
companion object {
private const val FRAGMENT_DUAL_START = "FragmentDualStart"
private const val FRAGMENT_DUAL_END = "FragmentDualEnd"
private const val FRAGMENT_SINGLE_SCREEN = "FragmentSingleScreen"
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_sample)
registerWindowInfoFlow()
}
private fun registerWindowInfoFlow() {
val windowInfoRepository = windowInfoRepository()
lifecycleScope.launch(Dispatchers.Main) {
lifecycle.repeatOnLifecycle(Lifecycle.State.STARTED) {
windowInfoRepository.windowLayoutInfo.collectIndexed { index, info ->
if (index == 0) {
onScreenInfoChanged(info)
}
}
}
}
}
/**
* Called whenever the screen info was changed.
* @param windowLayoutInfo object used to retrieve screen information
*/
private fun onScreenInfoChanged(windowLayoutInfo: WindowLayoutInfo) {
when {
windowLayoutInfo.isInDualMode() -> setupDualScreenFragments()
else -> setupSingleScreenFragments()
}
}
/**
* Adds fragments for the single screen mode
*/
private fun setupSingleScreenFragments() {
if (supportFragmentManager.findFragmentByTag(FRAGMENT_SINGLE_SCREEN) == null) {
supportFragmentManager.inTransaction {
replace(R.id.first_container_id, SingleScreenFragment(), FRAGMENT_SINGLE_SCREEN)
}
}
}
/**
* Adds fragments for the dual screen mode
*/
private fun setupDualScreenFragments() {
if (supportFragmentManager.findFragmentByTag(FRAGMENT_DUAL_START) == null &&
supportFragmentManager.findFragmentByTag(FRAGMENT_DUAL_END) == null
) {
supportFragmentManager.inTransaction {
replace(R.id.first_container_id, DualStartFragment(), FRAGMENT_DUAL_START)
}
supportFragmentManager.inTransaction {
replace(R.id.second_container_id, DualEndFragment(), FRAGMENT_DUAL_END)
}
}
}
}
inline fun FragmentManager.inTransaction(func: FragmentTransaction.() -> Unit) {
val fragmentTransaction = beginTransaction()
fragmentTransaction.func()
fragmentTransaction.commit()
}