Skip to content

Instantly share code, notes, and snippets.

@ZakTaccardi
Created May 20, 2020 17:22
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ZakTaccardi/c7df2379f5dad4b69d3c77ee46ca4168 to your computer and use it in GitHub Desktop.
Save ZakTaccardi/c7df2379f5dad4b69d3c77ee46ca4168 to your computer and use it in GitHub Desktop.
A practical example on why Composition over Inheritance matters for your codebase
/**
* Solution 1 = Manual
*/
internal class MyManualFragment(
private val viewModel: ViewModel
) : Fragment() {
private var startedScope: CoroutineScope? = null
override fun onStart() {
super.onStart()
startedScope = CoroutineScope(Dispatchers.Main.immediate)
startedScope!!.launch {
val ui = Ui(requireView())
viewModel.states
.onEach { ui.render(it) }
.launchWhenStartedIn(viewLifecycleOwner)
}
}
override fun onStop() {
startedScope!!.job.cancel()
super.onStop()
}
}
/**
* Solution 2 = Inheritance
*/
internal class InheritanceFragment(
private val viewModel: ViewModel
) : CoroutineFragment() {
override fun onViewCreated(scope: CoroutineScope, view: View, savedInstanceState: Bundle?) {
scope.launch {
val ui = Ui(requireView())
viewModel.states
.onEach { ui.render(it) }
.launchWhenStartedIn(viewLifecycleOwner)
}
}
}
/**
* Solution 3: Composition
*/
internal class CompositionFragment(
viewModel: ViewModel
) : Fragment() {
init {
viewLifecycleScope.launchWhenCreated {
val ui = Ui(requireView())
viewModel.states
.onEach { ui.render(it) }
.launchWhenStartedIn(this)
}
}
}
abstract class CoroutineFragment : Fragment() {
open fun onCreate(scope: CoroutineScope, savedInstanceState: Bundle?) {}
open fun onCreateView(
scope: CoroutineScope,
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
return null
}
open fun onViewCreated(scope: CoroutineScope, view: View, savedInstanceState: Bundle?) {}
open fun onStart(scope: CoroutineScope) {}
open fun onResume(scope: CoroutineScope) {}
}
typealias State = Int
interface ViewModel {
val states: Flow<State>
}
class Ui(private val view: View) {
fun render(state: State) {
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment