Skip to content

Instantly share code, notes, and snippets.

@ntoskrnl
Forked from anonymous/Presenter.kt
Created January 18, 2017 23:51
Show Gist options
  • Save ntoskrnl/44f6a26ded95665544501e888cb0b00e to your computer and use it in GitHub Desktop.
Save ntoskrnl/44f6a26ded95665544501e888cb0b00e to your computer and use it in GitHub Desktop.
Android. Example of how to store presenter in retained fragment and enable it to persist and restore view state.
interface Presenter<in V, in R> {
fun create()
fun attachRouter(router: R)
fun attachView(view: V)
fun detachView()
fun detachRouter()
fun destroy()
}
import android.os.Bundle
interface PresenterProvider {
fun providePresenter(key: String, savedState: Bundle?): Presenter<*, *>
}
import android.content.Context
import android.os.Bundle
import android.support.v4.app.Fragment
class PresenterRetainedFragment() : Fragment() {
private var presenterProvider: PresenterProvider? = null
private val presenters = mutableMapOf<String, Presenter<*, *>>()
override fun onAttach(context: Context?) {
super.onAttach(context)
presenterProvider = context as? PresenterProvider
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
retainInstance = true
if (savedInstanceState != null) {
savedInstanceState.getStringArray("keys")
.filter { it !in presenters.keys }
.map { key ->
key to presenterProvider?.providePresenter(key, savedInstanceState.getBundle("$key.state"))
}
.forEach {
val (key, presenter) = it
if (presenter != null) {
presenters.put(key, presenter)
presenter.create()
}
}
}
}
override fun onSaveInstanceState(outState: Bundle?) {
super.onSaveInstanceState(outState)
outState?.putStringArray("keys", presenters.keys.toTypedArray())
presenters.entries.forEach { entry ->
val (key, presenter) = entry
val state = Bundle()
(presenter as? StatefulPresenter)?.saveState(state)
outState?.putBundle("$key.state", state)
}
}
override fun onDestroy() {
if (isRemoving) {
presenters.values.forEach { it.destroy() }
presenters.clear()
}
super.onDestroy()
}
fun addPresenter(key: String, presenter: Presenter<*, *>) {
presenters[key] = presenter
}
fun getPresenter(key: String): Presenter<*, *>? {
return presenters[key]
}
}
import android.support.v4.app.Fragment
import android.support.v4.app.FragmentActivity
import android.support.v4.app.FragmentManager
fun <P : Presenter<V, R>, V, R> FragmentManager.getOrCreatePresenter(key: String, provider: PresenterProvider): P {
var container = findFragmentByTag("presenters") as PresenterRetainedFragment?
if (container == null) {
container = PresenterRetainedFragment()
beginTransaction()
.add(container, "presenters")
.commitNow()
}
val foundPresenter = container.getPresenter(key)
return when (foundPresenter) {
null -> {
val newPresenter = provider.providePresenter(key, null)
container.addPresenter(key, newPresenter)
newPresenter.create()
@Suppress("UNCHECKED_CAST")
newPresenter as P
}
else -> {
@Suppress("UNCHECKED_CAST")
foundPresenter as P
}
}
}
fun <P : Presenter<V, R>, V, R> Fragment.getOrCreatePresenter(key: String): P {
return getOrCreatePresenter<P, V, R>(key, this as PresenterProvider)
}
fun <P : Presenter<V, R>, V, R> Fragment.getOrCreatePresenter(key: String, provider: PresenterProvider): P {
return fragmentManager.getOrCreatePresenter<P, V, R>(key, provider)
}
fun <P : Presenter<V, R>, V, R> FragmentActivity.getOrCreatePresenter(key: String): P {
return getOrCreatePresenter<P, V, R>(key, this as PresenterProvider)
}
fun <P : Presenter<V, R>, V, R> FragmentActivity.getOrCreatePresenter(key: String, provider: PresenterProvider): P {
return supportFragmentManager.getOrCreatePresenter<P, V, R>(key, provider)
}
import android.os.Bundle
interface StatefulPresenter {
fun saveState(state: Bundle)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment