Thanks for thorough comment!
My article is about "solving task", not "bringing extra". If AndroidX Lifecycle fits your tasks, you should totally stick with it.
Idea was to have more fine-grained control than in AndroidX Lifecycle, in case you need it.
First and foremost, I created ShownFragment which I later add as plugin to BaseFragment (thus composition). ShownFragment is self-contained.
If you need listening to specific methods of Fragment, then that's it.
In case you want your plugin to provide functionality to external consumers, you have two ways:
- Expose list of attached plugins via BaseFragment and cast to specific class.
- Create interface with method implementations.
First option requires passing reference to actual fragment to each listener to allow it taking actions.
In article I picked second way as it allows to leave ShownFragment intact (SRP) by adding functionality with one line of code to *containing* fragment.
And as in Kotlin we can use inheritance on companion object, it means that inheritance on *original* Fragment class was not used.
I.e. I used both composition and inheritance here.
Your point is valid in general. If objective is to reuse showOnce, then it is only partially achieved as boilerplate is reduced but you still need to apply it in each fragment.
For my specific example dividing data (ShownFragment) and methods (ShowOnceDialogFragment interface) is not optimal, but can be worthy in other cases.
Probably it is worth investigating first option too and than compare them.
ViewModel (state of plugin) is beyond scope of this article. It can be an improvement, but does not add to original idea of article.
IMO onSaveInstanceState is fine for simple cases.
Typo - fixed.