Last active
March 4, 2019 16:50
-
-
Save brescia123/10f8c935984272fea2c7263c1d77465d to your computer and use it in GitHub Desktop.
Main components for lifecycle-aware presenters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import java.lang.ref.WeakReference | |
/** | |
* Base Interface for all the presenters. | |
* | |
* @param T The type of view (which extends [View]) the presenter is controlling. | |
*/ | |
interface PresenterApi<in T : View> { | |
fun onAttach(v: T) | |
fun onDetach() | |
} | |
/** Base Class for all the presenters. It takes care of implementing the attach/detach view mechanism. */ | |
abstract class Presenter<T : View> : PresenterApi<T> { | |
/** holds the view reference when it is attached. if the Presenter is not attached ot any View it is null. */ | |
private var viewRef: WeakReference<T>? = null | |
/** convenient method to get the View */ | |
fun view(): T? = viewRef?.get() | |
/** | |
* This method should be called every time a View is attached to the Presenter (e.g. configuration changes) | |
* or it is re-created. Here the presenter should render the view. | |
* (typically within onStart()) | |
* | |
* @param v the [View] to be attached | |
*/ | |
override fun onAttach(v: T) { | |
this.viewRef = WeakReference(v) | |
} | |
/** | |
* This method should be called every time the View is detached from the Presenter (e.g. configuration changes). | |
* (typically within onStop()) | |
*/ | |
override fun onDetach() { | |
viewRef?.clear() | |
viewRef = null | |
} | |
} | |
/** Base Interface for all the components (Activities, Fragments..) that act as views in MVP. */ | |
interface View |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import android.os.Bundle | |
import android.support.v4.app.LoaderManager | |
import android.support.v4.content.Loader | |
import android.support.v7.app.AppCompatActivity | |
abstract class PresenterActivity<V : View, P : Presenter<V>> : AppCompatActivity() { | |
protected var presenter: P? = null | |
abstract val presenterGenerator: () -> P | |
override fun onCreate(savedInstanceState: Bundle?) { | |
super.onCreate(savedInstanceState) | |
supportLoaderManager.initLoader(101, null, object : LoaderManager.LoaderCallbacks<P> { | |
override fun onCreateLoader(id: Int, args: Bundle?): Loader<P> { | |
return PresenterLoader( | |
this@PresenterActivity, | |
presenterGenerator) | |
} | |
override fun onLoadFinished(loader: Loader<P>, data: P) { | |
presenter = data | |
} | |
override fun onLoaderReset(loader: Loader<P>) { | |
presenter?.onDestroy() | |
presenter = null | |
} | |
}) | |
} | |
override fun onStart() { | |
super.onStart() | |
presenter?.onAttach(this as V) | |
} | |
override fun onStop() { | |
presenter?.onDetach() | |
super.onStop() | |
} | |
override fun onDestroy() { | |
super.onDestroy() | |
presenter?.onDestroy() | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import android.os.Bundle | |
import android.support.v4.app.Fragment | |
import android.support.v4.app.LoaderManager | |
import android.support.v4.content.Loader | |
/** Base Activity ensuring that the given Presenter is detached form the the Activity lifecycle */ | |
abstract class PresenterFragment<V : View, P : Presenter<V>> : Fragment() { | |
/** Factory function that has to be implemented by subclasses to provide a Presenter */ | |
abstract val presenterGenerator: () -> P | |
protected var presenter: P? = null | |
private val loaderCallbacks: LoaderManager.LoaderCallbacks<P> = object : LoaderManager.LoaderCallbacks<P> { | |
override fun onCreateLoader(id: Int, args: Bundle?): Loader<P> = | |
PresenterLoader(context, presenterGenerator) | |
override fun onLoadFinished(loader: Loader<P>, data: P) { | |
presenter = data | |
} | |
override fun onLoaderReset(loader: Loader<P>) { | |
presenter = null | |
} | |
} | |
override fun onCreate(savedInstanceState: Bundle?) { | |
super.onCreate(savedInstanceState) | |
loaderManager.initLoader(101, null, loaderCallbacks) | |
} | |
override fun onStart() { | |
super.onStart() | |
presenter?.onAttach(this as V) | |
} | |
override fun onStop() { | |
presenter?.onDetach() | |
super.onStop() | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import android.content.Context | |
import android.support.v4.content.Loader | |
/** Android Loader used to decouple [Presenter] from Activity/Fragment lifecycle. */ | |
class PresenterLoader<T : Presenter<*>>(context: Context, private val factory: () -> T) : Loader<T>(context) { | |
private var presenter: T? = null | |
override fun onStartLoading() { | |
if (presenter != null) | |
deliverResult(presenter as T) | |
else | |
forceLoad() | |
} | |
override fun onForceLoad() { | |
presenter = factory() | |
deliverResult(presenter as T) | |
} | |
override fun onReset() { | |
presenter = null | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment