title: ViewModel scoping across Fragments in same Activity
body: <p>I'm having a problem that I think traces back to <code>ViewModel</code> scoping. I have two fragments in the same nav graph under the same activity. The first fragment, <code>LoginFragment</code> instantiates a <code>UserDataViewModel</code> and populates some of its data in an object called <code>UserData</code></p>
  
  <p>The second fragment, <code>TodayFragment</code> is supposed to pick up <code>UserDataViewModel</code> and use the attributes already populated to do further work. However, by the time that <code>TodayFragment</code> attempts to access the <code>UserData</code> object, that object is null. To emphasize, <code>UserDataViewModel</code> still has the same memory address, but the problem is that it has lost the reference to its data value.</p>
  
  <p>I've stripped this down so that the data is simply pulling a string from <code>SharedPreferences</code> and parsing it using GSON. </p>
  
  <p><strong>LoginFragment</strong>:</p>
  
  <pre><code>private lateinit var userDataViewModel: UserDataViewModel
  
  override fun onCreate(savedInstanceState: Bundle?) {
      super.onCreate(savedInstanceState)
      MyApplication.appComponent?.inject(this)
      prefs = PreferenceManager.getDefaultSharedPreferences(context)
  
      userDataViewModel = activity?.run {
          ViewModelProviders
              .of(this, UserDataViewModelFactory(prefs, dataFetcherService))
              .get(UserDataViewModel::class.java)
      } ?: throw Exception("Invalid Activity")
  
      userDataViewModel.getUserData()
  }
  </code></pre>
  
  <p><strong>TodayFragment</strong></p>
  
  <pre><code>override fun onCreate(savedInstanceState: Bundle?) {
      super.onCreate(savedInstanceState)
      prefs = PreferenceManager.getDefaultSharedPreferences(activity)
  
      userDataViewModel = activity?.run {
          ViewModelProviders
              .of(this, UserDataViewModelFactory(prefs, dataFetcherService))
              .get(UserDataViewModel::class.java)
      } ?: throw Exception("Invalid Activity")
  }
  
  override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
      super.onViewCreated(view, savedInstanceState)
  
      userDataViewModel
          .getUserData()
          .observe(this, Observer {
              clubId = it.club_id  // &lt;-- this is where it crashes since 'it' is null
          })
  }
  </code></pre>
  
  <p><strong>UserDataViewModel.kt</strong></p>
  
  <pre><code>class UserDataViewModel(
      prefs: SharedPreferences,
      dataFetcherService: DataFetcherService)
      : ViewModel() {
  
      private val useCase = UserDataUseCase(prefs, dataFetcherService)
  
      val userData: MutableLiveData&lt;UserData&gt; by lazy {
          MutableLiveData&lt;UserData&gt;().apply { loadUserData() }
      }
  
      fun getUserData(): LiveData&lt;UserData&gt; {
          return userData
      }
  
      private fun loadUserData() {
          viewModelScope.launch {
              withContext(Dispatchers.IO) {
                  try {
                      return@withContext useCase.loadUserData(USER_UNKNOWN)
                  } catch (t: Throwable) {
                      return@withContext null
                  }
              }
                  ?.let {
                      userData.postValue(it)
                  }
          }
      }
  }
  </code></pre>
  
  <p>Where it is weird is in the <code>getUserData()</code> method in the view model. When I set a breakpoint on these lines:</p>
  
  <p><code>return userData</code><br>
  <code>MutableLiveData&lt;UserData&gt;().apply { loadUserData() }</code><br>
  <code>return@withContext useCase.loadUserData(USER_UNKNOWN)</code><br></p>
  
  <p>those breakpoints are all hit the LoginFragment. But when it enters TodayFragment, it hits on <code>return userData</code> in the view model and then immediately jumps back to the observer inside of TodayFragment with a null pointer exception for the value inside of the view model. </p>
  
  <p>I think that makes sense to the extent that the view model itself is instantiated, but why is the value <em>inside</em> the view model null?</p>
  
  <p>For debugging purposes, I am hardcoding a response from the usecase and repository to ensure that there is a value populated in the <code>ViewModel</code>.</p>
  
  <p><strong>Screen Shot from LoginFragment</strong>
  <a href="https://i.stack.imgur.com/KbVEu.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/KbVEu.png" alt="enter image description here"></a></p>
  
  <p><strong>Screen Shot from TodayFragment (extends AbstractWorkoutFragment)</strong><br>
  <em>Note how <code>mData</code> is now null but the ViewModel is the same.</em>
  <a href="https://i.stack.imgur.com/58lxs.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/58lxs.png" alt="enter image description here"></a></p>