https://kotlinlang.org logo
#android
Title
# android
o

Orhan Tozan

04/14/2020, 1:17 PM
When is an Android ViewModel's
init {}
called? I know that LiveData's only get initialized after observing them, but what about the init block? On Activity onCreate?
a

aipok

04/14/2020, 1:38 PM
It depends when you create it. The
init
will be called first time ViewModel is created. For example when it is being injected or when you create it from factory and it will not be called in case fragment get it as a shared instance.
o

Orhan Tozan

04/14/2020, 1:38 PM
I am using Koin, apparently init gets called lazily after first usage of viewmodel
a

aipok

04/14/2020, 1:41 PM
Then
init
will be called in the same method where you call it for the first time. In case it is in Activity:onCreate, then it will be called there.
o

Orhan Tozan

04/14/2020, 1:42 PM
Yes indeed, I was asking because my viewmodel right now only is used for its init block but it wasnt doing anything. I am now calling viewmodel.toString() in onCreate just so that it gets triggered.
It works now
a

aipok

04/14/2020, 1:45 PM
well, correctly would be to just assign the variable with
late init
in your activity using
get()
from Koin. Not sure that calling the viewModel.toString is a good idea, since some other developer could break it very easy, he might think that it is some leftover from debugging. I had such cases in past 😄
o

Orhan Tozan

04/14/2020, 1:46 PM
image.png
This is how I define a viewmodel in koin in activity
a

aipok

04/14/2020, 1:49 PM
you can define it as
Copy code
private lateinit var viewModel: HomeViewModel

override fun onCreate(savedInstanceState: Bundle?) {
  super.onCreate(savedInstanceState)
   viewModel = getViewModel<HomeViewModelUsingEngine>()
}
something like this should do the trick
m

Matt Thompson

04/14/2020, 3:43 PM
or move logic out of the init block and into a function that is explicitly called in onCreate - might be clearer
☝️ 2
o

Orhan Tozan

04/14/2020, 6:01 PM
I thought about that, something like an onStart() method, but I see alot of examples, including Google's, use the init block. So I thought it is better practice to do so myself.
b

Bruno_

04/15/2020, 8:23 AM
if you decompile the kotlin code with init
Copy code
class Foo(private val string: String) {
    init {
        val a = 2 + 2
        println(a)
        println(string)
    }
}
you'll get the following thing
Copy code
public final class Foo {
   private final String string;

   public Foo(@NotNull String string) {
      Intrinsics.checkParameterIsNotNull(string, "string");
      super();
      this.string = string;
      int a = 4;
      boolean var3 = false;
      System.out.println(a);
      String var5 = this.string;
      boolean var4 = false;
      System.out.println(var5);
   }
}
so init is basically a constructor, it's not lazy by any means
m

myanmarking

04/15/2020, 1:29 PM
init {} is not a viewModel thing, but kotlin's isnt it? Init is called just after constructor return
252 Views