Your instincts can be right. Breaking changes can be caused by name conflicts, variable shadowing, wrong imports, wrong assignment to values. But these days, the demand for features is increasing, in such that you need the public accessor. Just have this rules in your conscience:
- Interfaces are powerful at class to class communication
- Inherit what is important, override what is implemented already, pass to param to lessen global var damage
- If a variable can be stored in another global form, consider it with regard to size(ram matters), speed of access(ux matters), security(keys matter) and volatility(nulls matter).
Now looking at your code, I can see you have a fragment system that is based on values/functions stored in the main activity, that provides the context for the fragment. If you apply the first point: Your fragment will implement a BaseFragment that already some context cast i.e. lateinit var mainActivity: MainActivity
then you can mainActivity.viewModel
anywhere in your fragment without casting. And this is cleaner
Applying the second point: in the BaseFragment (that will be inherited by AnotherFragment)
abstract var viewModel: ViewModel
abstract fun initList()
open var countryList = mutableListOf()
open fun onScale(detector: ScaleGestureDetector) { //pinch: increase visible country list like some nice zoom effect .. etc }
if most or all of your fragments need similar functions or variables, make abstract to something you can forget will crash the app, make open for those 'features but I dont need to rewrite so I'll call super.function' functions. Make a var open if some super function overrides it, and just put var if you seriously dont know when you want it and when to change it.
On the third point, Android in the early stages, we learnt the hard way that context doesn't last forever even if your app is running. Rotation and lifecycle functions will swap it rough and fast. So consider other storage ways. I still dont trust requireContext/Activity/view for context, so cast with caution.