Open mradzinski opened 7 years ago
Based on that PR I linked above, I'm wondering if something like this might work...
MvpRestoreViewOnCreateController
(Based on your MvpController
class):
abstract class MvpRestoreViewOnCreateController<V : MvpView, P : MvpPresenter<V>>(args: Bundle?) :
RestoreViewOnCreateController(args), MvpView, MvpConductorDelegateCallback<V, P> {
private var presenter: P? = null
init {
addLifecycleListener(getMosbyLifecycleListener());
}
constructor(): this(null)
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup, savedViewState: Bundle?): View {
throw UnsupportedOperationException("not implemented")
}
override fun getMvpView(): V {
return this as V
}
override fun setPresenter(presenter: P) {
this.presenter = presenter
}
override fun getPresenter(): P? {
return presenter
}
/**
* This method is for internal purpose only.
*
* **Do not override this until you have a very good reason**
* @return Mosby's lifecycle listener so that
*/
private fun getMosbyLifecycleListener(): Controller.LifecycleListener {
return MvpConductorLifecycleListener(this)
}
}
And then BaseMvpDialogController
based on the PR but extending MvpRestoreViewOnCreateController
/**
* A controller that displays a dialog window, floating on top of its activity's window.
* This is a wrapper over [Dialog] object like [android.app.DialogFragment].
* Implementations should override this class and implement [onCreateDialog] to create a custom
* dialog, such as an [android.app.AlertDialog]
*/
abstract class MvpDialogController<V : MvpView, P : MvpPresenter<V>>(args: Bundle?) :
RestoreViewOnCreateController<V, P>(args) {
companion object {
private val SAVED_DIALOG_STATE_TAG = "android:savedDialogState"
}
@get:Nullable
private lateinit var dialog: Dialog
private set
private var dismissed: Boolean = false
/**
* Convenience constructor for use when no arguments are needed.
*/
protected constructor() : this(null)
@NonNull
override fun onCreateView(@NonNull inflater: LayoutInflater, @NonNull container: ViewGroup, @Nullable savedViewState: Bundle?): View {
dialog = onCreateDialog(savedViewState)
dialog.ownerActivity = activity
dialog.setOnDismissListener({ dismissDialog() })
if (savedViewState != null) {
val dialogState = savedViewState.getBundle(SAVED_DIALOG_STATE_TAG)
if (dialogState != null) {
dialog.onRestoreInstanceState(dialogState)
}
}
return View(activity) //stub view
}
override fun onSaveViewState(@NonNull view: View, @NonNull outState: Bundle) {
super.onSaveViewState(view, outState)
val dialogState = dialog.onSaveInstanceState()
outState.putBundle(SAVED_DIALOG_STATE_TAG, dialogState)
}
override fun onAttach(@NonNull view: View) {
super.onAttach(view)
dialog.show()
}
override fun onDetach(@NonNull view: View) {
super.onDetach(view)
dialog.hide()
}
override fun onDestroyView(@NonNull view: View) {
super.onDestroyView(view)
dialog.setOnDismissListener(null)
dialog.dismiss()
}
/**
* Display the dialog, create a transaction and pushing the controller.
* @param router The router on which the transaction will be applied
* @param tag The tag for this controller
*/
fun showDialog(@NonNull router: Router, @Nullable tag: String) {
dismissed = false
router.pushController(RouterTransaction.with(this)
.pushChangeHandler(VerticalChangeHandler(150, false))
.popChangeHandler(VerticalChangeHandler(150, false))
.tag(tag))
}
/**
* Dismiss the dialog and pop this controller
*/
@Suppress("MemberVisibilityCanPrivate")
fun dismissDialog() {
if (dismissed) {
return
}
router.popController(this)
dismissed = true
}
/**
* Build your own custom Dialog container such as an [android.app.AlertDialog]
*
* @param savedViewState A bundle for the view's state, which would have been created in [onSaveViewState] or `null` if no saved state exists.
* @return Return a new Dialog instance to be displayed by the Controller
*/
@NonNull
protected abstract fun onCreateDialog(@Nullable savedViewState: Bundle?): Dialog
}
Let me know you thoughts mate.
Hey @sockeqwe, I have an use case where I need to display a FragmentDialog through a controller. I've noticed that there's a PR on the conductor repo to include a DialogController.
How would you handle such situations using mosby-conductor? I guess that following the MVP pattern the FragmentDialog shouldn't have much logic and that the logic should be handled by a presenter, but I can't seem to think of a way of having a presenter attached to it.