2021年3月14日星期日

Null Pointer Exception received when I'm trying to implement Manual Dependency Injection in Android

So I was learning Manual Dependency Injection from the Android Developers documentation to implement a simple saving mechanism using the Room database library. However, it has been causing the NullPointerException in the Container class:

2021-03-15 07:12:08.370 23721-23721/com.arpansircar.Practice.dependencyinjectionpractice E/AndroidRuntime: FATAL EXCEPTION: main      Process: com.arpansircar.Practice.dependencyinjectionpractice, PID: 23721      java.lang.RuntimeException: Unable to instantiate application com.arpansircar.practice.dependencyinjectionpractice.di.MyApplication: java.lang.NullPointerException: Attempt to invoke virtual method 'android.content.Context android.content.Context.getApplicationContext()' on a null object reference          at android.app.LoadedApk.makeApplication(LoadedApk.java:1230)          at android.app.ActivityThread.handleBindApplication(ActivityThread.java:6583)          at android.app.ActivityThread.access$1400(ActivityThread.java:227)          at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1890)          at android.os.Handler.dispatchMessage(Handler.java:107)          at android.os.Looper.loop(Looper.java:224)          at android.app.ActivityThread.main(ActivityThread.java:7592)          at java.lang.reflect.Method.invoke(Native Method)          at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:539)          at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:950)           Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'android.content.Context android.content.Context.getApplicationContext()' on a null object reference              at android.content.ContextWrapper.getApplicationContext(ContextWrapper.java:128)              at com.arpansircar.practice.dependencyinjectionpractice.di.MyApplication.<init>(MyApplication.kt:7)              at java.lang.Class.newInstance(Native Method)              at android.app.AppComponentFactory.instantiateApplication(AppComponentFactory.java:76)              at androidx.core.app.CoreComponentFactory.instantiateApplication(CoreComponentFactory.java:52)              at android.app.Instrumentation.newApplication(Instrumentation.java:1156)              at android.app.LoadedApk.makeApplication(LoadedApk.java:1222)              at android.app.ActivityThread.handleBindApplication(ActivityThread.java:6583)               at android.app.ActivityThread.access$1400(ActivityThread.java:227)               at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1890)               at android.os.Handler.dispatchMessage(Handler.java:107)               at android.os.Looper.loop(Looper.java:224)               at android.app.ActivityThread.main(ActivityThread.java:7592)               at java.lang.reflect.Method.invoke(Native Method)               at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:539)               at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:950)   

Here are the classes where I figure there could be an error.

AppContainer.kt

package com.arpansircar.practice.dependencyinjectionpractice.di    import android.content.Context  import com.arpansircar.practice.dependencyinjectionpractice.repository.UserRepository  import com.arpansircar.practice.dependencyinjectionpractice.room.UserDao  import com.arpansircar.practice.dependencyinjectionpractice.room.UserDatabase  import com.arpansircar.practice.dependencyinjectionpractice.viewmodel.UserViewModelFactory    class AppContainer(context: Context) {        private val userDao: UserDao = UserDatabase.getInstance(context).userDao()        private val userRepository: UserRepository = UserRepository(userDao)        val userViewModelFactory: UserViewModelFactory = UserViewModelFactory(userRepository)    }  

MyApplication.kt

package com.arpansircar.practice.dependencyinjectionpractice.di    import android.app.Application    class MyApplication : Application() {        val appContainer = AppContainer(applicationContext)    }  

MainActivity.kt

package com.arpansircar.practice.dependencyinjectionpractice.view    import androidx.appcompat.app.AppCompatActivity  import android.os.Bundle  import androidx.navigation.NavController  import androidx.navigation.fragment.NavHostFragment  import androidx.navigation.fragment.findNavController  import com.arpansircar.practice.dependencyinjectionpractice.di.AppContainer  import com.arpansircar.practice.dependencyinjectionpractice.di.MyApplication  import com.arpansircar.practice.dependencyinjectionpractice.R    class MainActivity : AppCompatActivity() {        private var appContainer: AppContainer? = null      private lateinit var navController: NavController        override fun onCreate(savedInstanceState: Bundle?) {          super.onCreate(savedInstanceState)          setContentView(R.layout.activity_main)          appContainer = (application as MyApplication).appContainer            val navHostFragment: NavHostFragment =              supportFragmentManager.findFragmentById(R.id.nav_host_fragment_container) as NavHostFragment          navController = navHostFragment.findNavController()      }        override fun onDestroy() {          super.onDestroy()          appContainer = null      }    }  

RegistrationFragment.kt

package com.arpansircar.practice.dependencyinjectionpractice.view    import android.os.Bundle  import android.view.LayoutInflater  import android.view.View  import android.view.ViewGroup  import androidx.fragment.app.Fragment  import androidx.lifecycle.ViewModelProvider  import com.arpansircar.practice.dependencyinjectionpractice.databinding.FragmentRegistrationBinding  import com.arpansircar.practice.dependencyinjectionpractice.di.MyApplication  import com.arpansircar.practice.dependencyinjectionpractice.room.UserEntity  import com.arpansircar.practice.dependencyinjectionpractice.viewmodel.UserViewModel    class RegistrationFragment : Fragment(), View.OnClickListener {        private lateinit var binding: FragmentRegistrationBinding      private lateinit var userViewModel: UserViewModel        override fun onCreate(savedInstanceState: Bundle?) {          super.onCreate(savedInstanceState)          val appContainer = (context as MyApplication).appContainer            userViewModel = ViewModelProvider(              this,              appContainer.userViewModelFactory          ).get(UserViewModel::class.java)      }        override fun onCreateView(          inflater: LayoutInflater,          container: ViewGroup?,          savedInstanceState: Bundle?      ): View {          binding = FragmentRegistrationBinding.inflate(              inflater,              container,              false          )            return binding.root      }        override fun onStart() {          super.onStart()          binding.createAccountButton.setOnClickListener(this)          binding.getAllAccountsButton.setOnClickListener(this)      }        override fun onClick(view: View?) {          when (view) {                binding.createAccountButton -> {                  val name: String = binding.userNameTextInputEditText.text.toString()                  val userName: String = binding.userUsernameTextInputEditText.text.toString()                  val password: String = binding.userPasswordTextInputEditText.text.toString()                    val userEntity = UserEntity(0, name, userName, password)                  userViewModel.insertUsers(userEntity)              }                binding.getAllAccountsButton -> {                }          }      }  }  

UserViewModelFactory.kt

package com.arpansircar.practice.dependencyinjectionpractice.viewmodel    import androidx.lifecycle.ViewModel  import androidx.lifecycle.ViewModelProvider  import com.arpansircar.practice.dependencyinjectionpractice.repository.UserRepository    class UserViewModelFactory(private val userRepository: UserRepository) : ViewModelProvider.Factory {        @Suppress("UNCHECKED_CAST")      override fun <T : ViewModel?> create(modelClass: Class<T>): T {          if (modelClass.isAssignableFrom(UserViewModel::class.java)) {              return UserViewModel(userRepository) as T          }            throw IllegalArgumentException("Unknown ViewModel Class")      }    }  

UserViewModel.kt

package com.arpansircar.practice.dependencyinjectionpractice.viewmodel    import androidx.lifecycle.LiveData  import androidx.lifecycle.ViewModel  import androidx.lifecycle.viewModelScope  import com.arpansircar.practice.dependencyinjectionpractice.repository.UserRepository  import com.arpansircar.practice.dependencyinjectionpractice.room.UserEntity  import kotlinx.coroutines.Dispatchers.IO  import kotlinx.coroutines.launch    class UserViewModel(private val userRepository: UserRepository) : ViewModel() {        fun insertUsers(userEntity: UserEntity) {          viewModelScope.launch(IO) {              userRepository.insertUser(userEntity)          }      }        fun getUsers(): LiveData<List<UserEntity>> {          return userRepository.selectUsers()      }    }  

Specifically, the error points to line no. 7 in the MyApplication.kt class

val appContainer = AppContainer(applicationContext)  

stating

Attempt to invoke virtual method 'android.content.Contextandroid.content.Context.getApplicationContext()' on a null object reference

I can't figure out how the context can be null considering that I'm invoking the MyApplication class in the onCreate method of my MainActivity.kt class

override fun onCreate(savedInstanceState: Bundle?) {          super.onCreate(savedInstanceState)          setContentView(R.layout.activity_main)          appContainer = (application as MyApplication).appContainer  ...  }  

and in the onCreate method of my RegistrationFragment.kt class

override fun onCreate(savedInstanceState: Bundle?) {      super.onCreate(savedInstanceState)      val appContainer = (context as MyApplication).appContainer    userViewModel = ViewModelProvider(      this,      appContainer.userViewModelFactory  ).get(UserViewModel::class.java)  

}

I mean, shouldn't the activity and fragment been started and initialized with a context within these methods?

https://stackoverflow.com/questions/66631506/null-pointer-exception-received-when-im-trying-to-implement-manual-dependency-i March 15, 2021 at 10:06AM

没有评论:

发表评论