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
没有评论:
发表评论