Fragment-Manager-Statushandler

Wichtig

In diesem Artikel werden Funktionen und Anleitungen beschrieben, die sich in der öffentlichen Vorschau befinden und vor der allgemeinen Verfügbarkeit noch wesentlich geändert werden können. Microsoft übernimmt keine Garantie, weder ausdrücklich noch stillschweigend, für die hier bereitgestellten Informationen.

FragmentManagerStateHandler ist eine Klasse zur Unterstützung der Wiederherstellung von Fragmenten bei einem auftretenden Übergang des Bildschirmmodus.

Wenn wir die App vom Doppelbildschirm- auf den Einzelbildschirmmodus umstellen, werden alle Fragmente neu erstellt, selbst wenn sie nicht sichtbar sind.

Bei Verwendung dieser Bibliothek werden nur die erforderlichen Fragmente neu erstellt.

Da die Fragmente aus dem Aktivitätspaket wiederhergestellt werden, können wir zwei Pakete verwenden, die zur Laufzeit abhängig vom Überdeckungsmodus ausgetauscht werden – also ein Bündel für den Einzelbildschirm und ein weiteres für den überdeckenden Modus. Dies ist nur möglich, indem dem Aktivitätslebenszyklus ein Rückruf hinzugefügt wird und diese beiden Pakete innerhalb des onActivityPreCreated-Rückrufs ausgetauscht werden.

Die Komponente erkennt den aktuellen Bildschirmmodus automatisch und stellt nur die benötigten Fragmente wieder her, abhängig vom Bildschirmmodus.

Wichtig

Die Komponente funktioniert nur mit Aktivitäten aus AndroidX.

Verwendung

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()
}