is it all about null safety ?
TLDR : Snippet says all ~(0_<)~
Kotlin type system is designed in such a way that you are always aware of the nullable type properties in your codebase, which enables you to do appropriate handling so you don't do the Billion Dollar Mistake.
It provides many ways to cater nullable type properties elegantly without doing lots of branching, assertions, or ceremony. Some of the well-known ways are mentioned below :
- Compiler is aware of nullable references* (Java interpolation sometimes require more information in form of
- Null check Operators safe call operators such as
- Safe cast operators :
- Null check function such as
- Standard library Extension
getOrNull()type : predeclare of nullable type response
- Null handling collection such as
- The last one which I want to focus on is
lateinit modifier 🧐
So the basic gist of using lateinit modifier is to tell the compiler that this variable would be initalized late 💤, It will not allocate memory until initialized.
If we see this how it is related to nullable handling is because developers keep global variables 🌏 whose value is assigned later in the flow. So as a common practice by Java developer used to initialize global variables as null.
In Kotlin since people have access to `lateinit` modifier, they tend to initialize global variables🌏 using it, so they don't have to start off with a nullable type variable and don't have to do null handling every time they access the value of the object.
In my opinion, global variables 🌏 are a necessary evil 😈, because in a framework like Android they are more like a cache at the scope of activity or fragment(UI components) which can be destroyed anytime, So keeping them cached can cause memory leaks and other scope related issues which will doom😵 your code sooner or later, but we can't just ignore global variables🌏 the convenience they bring is much greater* (at the cost of maintenance) and they are sometimes the only solution/quick fix for a problem.
Global variables 🌏 should be
This totally depends on what you're storing in the variable, if its a View I will strongly suggest to keep it nullable so you can release it in the destructive lifecycle of your UI components, they are worthy to be null checked on every access.
If its a data component then you can use lateinit with giving a second thought.
if there is another problem laying inside using lateinit.
Unlike nullable type it will not give compiler error on access, it will directly blow on your face if you try to access it without initializing it, but devs are smart people, too smart for their own good 🤦🏻♂️. They use kotlin reflection operators
:: to check if lateinit variable is initialized or not before accessing it.
the problem with this approach is :
- First using reflection is a big no-no, they are hackish as f*** and Do you remember those good old Java days where Reflection is considered as bad practice and hack, those days are not gone my friend, In Kotlin some reflection operators are being used only for giving interpolation with Java APIs or those which are fast to execute. (Yes reflection APIs are slower prefs matter)
- Second, As I discussed Earlier if you forget to initialize ➕ now if you forget to check if it's not initialized from every access point it will blow your codebase, this is not true for nullable fields as the compiler will force you to null check them.
- Third, the obvious! you loose compiler support i.e no warning ⚠️ direct compilation, compiler cant tell you that the field your accessing is initialized or not. Yeah, you can say if you accidentally forgot to assign value to a nullable variable then did all
?:handle compiler won't tell you that you didn't assign value to your nullable type and code will not blow, but if you do that then admit it your dumb my friend 🤦🏻♂.
- Finally, you need to wait for garbage collection(GC) cycle to release your variables, which isn't a big deal as GC has grown very smart these days. but still, you get extra control using nullable types.💁🏻♀️
So my final verdict would be if you're using
lateinit make sure its initialize at entry point in your code base , it could be your
init block or first lifecycle call to your UI component creation (watch out you all fragment users), else prefer nullable type they are not always evil!.
Anyways That's All for today💻! See ya again in Next article. Peace!✌