Backstack for Model-View-Presenter (MVP) Views in a Fragment-less design, written in Kotlin.
With an MVP architecture, you may want to do away with Android's Fragments, keep Activities to a minimum, and have clean Models, Views and Presenters. To manage your Views, some kind of backstack is required...
Put this somewhere easily-accessible.
This can be done in one of two ways:
- a. In Android Studio, right-click your project in the 'Project' tab, and select Open Module Settings
- b. Click the + (circled) to add a module
- c. In the Create New Module window, under Import..., set the Source Directory to the inner
backstackmodule within the saved library project (i.e.backstack/backstack)
- a. Copy
backstack/backstack/build/outputs/aar/backstack-release.aar - b. Paste to
<app-name>/<app-module>/libs/ - c. Ensure your app module's Gradle build script imports
backstack-release.aar:
Gradle build configuration scripts are written in either Groovy DSL or Kotlin DSL (domain-specific language).
If Kotlin DSL (build.gradle.kts):
dependencies {
implementation(files("libs/backstack-release.aar"))
}If Groovy DSL (build.gradle):
dependencies {
implementation files('libs/backstack-release.aar')
}Ensure your Activity implements BackStack.ActivityInterface.
Below is a guide of an Activity implementation: you can view a working example in the backstackexample module of this project.
class MainActivity : AppCompatActivity(), BackStack.ActivityInterface {
private lateinit var binding: ActivityMainBinding
private val backstack = BackStack(this)
/**
* Notes:
* - View Binding (https://developer.android.com/topic/libraries/view-binding) is in-use
* - Content set, view binding, and Model object creation should be done before call
* to `backstack.onCreate()`.
*/
override fun onCreate(savedInstanceState: Bundle?) {
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
model = Model()
backstack.onCreate()
super.onCreate(savedInstanceState)
}
override fun onBackPressed() {
super.onBackPressed()
backstack.goBack()
}
override fun getInitialView(): BackStackView {
return ExampleView()
}
override fun addView(view: ViewGroup) {
binding.container.addView(view)
}
override fun removeAllViews() {
binding.container.removeAllViews()
}
/**
* I have opted to create the Model in onCreate().
*/
override fun getModel(): ModelInterface {
return model
}
override fun getContext(): Context {
return this
}
}Assumption: you already have an MVP architecture setup for this application - if not, see the code in backstackexample for an example:
class ExampleView: BackStackView() {
private lateinit var presenter: ExamplePresenterInterface
private lateinit var binding: ExampleViewBinding
/********** public */
override fun getLayout(): Int = R.layout.example_view
override fun onCreate(backstack: BackStackInterface, model: ModelInterface,
context: AndroidContextInterface) {
binding = ViewBinding.bind(view!!)
setupButtonOnClickListener()
/** This should be last as Presenter will likely use views defined above. **/
this.presenter = ExamplePresenter(this, model as ExampleModelInterface, backstack)
}
override fun onResume(context: AndroidContextInterface) {
binding = ViewBinding.bind(view!!)
this.presenter.onResume()
}
}- I have not tested any kind of compatibility with Jetpack Compose.
