Я получаю исключение java.lang.NullPointerException, чего, по моему мнению, не должно быть. Может ли кто-нибудь помочь мне с этим?

У меня есть интерфейс, который передается в модель представления из действия, в котором он реализован. Затем в модели представления он вызывает реализованный метод интерфейса. Внутри этого метода все, что я хочу сделать, это отобразить Toast, но я получаю нулевую ошибку при попытке получить доступ к контексту активности. Я не понимаю почему. Для ясности: внутри всех переопределенных методов, таких как onCreate, onStop, OnResume и т. д. Если я показываю всплывающее уведомление, оно работает нормально. Только когда внутри этого метода интерфейса контекст активности кажется нулевым. Я понятия не имею.

Это модуль рукояти

@Module
@InstallIn(SingletonComponent::class)
abstract class ToastListenerModule {
    @Binds
    abstract fun bindToastMessageListener(activity: SplashActivity): ToastMessageListener
}

Мой SplashActivity.kt

@AndroidEntryPoint
class SplashActivity @Inject constructor() : AppCompatActivity(), ToastMessageListener {
    private lateinit var binding: ActivitySplashBinding

    @Inject
    lateinit var auth: FirebaseAuth

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        installSplashScreen()
        binding = ActivitySplashBinding.inflate(layoutInflater)

        setContentView(binding.root)
    }

    override fun showToast(message: String) {
        //THIS IS WHERE THE PROBLEM IS WITH THE CONTEXT
        Toast.makeText(this, "MESSAGE", Toast.LENGTH_SHORT)
    }
}

Ниже у меня есть ViewModel:

@HiltViewModel
class AuthenticationViewModel @Inject constructor(
    private val auth: FirebaseAuth,
    private val toastListner: ToastMessageListener,
) : ViewModel() {
    val emailText = ObservableField<String>("")
    val passwordText = ObservableField<String>("")
    val nameText = ObservableField<String>("")

    fun onSubmitClicked(isLogin: Boolean) {
        if (isLogin) {
            val email = emailText.get()
            val password = passwordText.get()

            if (email.isNullOrEmpty() || password.isNullOrEmpty()) {
                println("Email or password is empty")
                return
            }
            auth.signInWithEmailAndPassword(emailText.get() ?: "", passwordText.get() ?: "")
                .addOnCompleteListener() { task ->
                    if (task.isSuccessful) {
                        toastListner.showToast("Login Successful")
                    } else {
                        val exception = task.exception
                        //THIS IS WHERE I CALL showToast
                        //AND YES IT IS GETTING CALLED AND EVERYTHING
                        toastListner.showToast("Login Failed: ${exception?.message}")
                    }
                }
        } else {
            println("SIGN Up BUTTON CLICKED ${emailText.get()} ${passwordText.get()}")
        }
    }

    fun isValidInput(): Boolean {
        val inputEm = emailText.get() ?: return false
        val inputPass = passwordText.get() ?: return false

        return inputEm.isNotEmpty() && inputPass.isNotEmpty()
    }
}

Моя ОШИБКА

 FATAL EXCEPTION: main                                                                                
                                                                                                            Process: com.example.findroomies, PID: 27661
                                                                                                        java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String android.content.Context.getPackageName()' on a null object referenceat android.content.ContextWrapper.getPackageName(ContextWrapper.java:173)
                                                                                                            at android.widget.Toast.<init>(Toast.java:174)
                                                                                                            at android.widget.Toast.makeText(Toast.java:498)
                                                                                                            at android.widget.Toast.makeText(Toast.java:487)
                                                                                                            at com.example.findroomies.ui.activities.SplashActivity.showToast(SplashActivity.kt:52)
                                                                                                            at com.example.findroomies.ui.viewmodels.AuthenticationViewModel.onSubmitClicked$lambda$0(AuthenticationViewModel.kt:35)
                                                                                                            at com.example.findroomies.ui.viewmodels.AuthenticationViewModel.$r8$lambda$b1GN3_M-m0Ij9SZCrkTUOa2z6PY(Unknown Source:0)
                                                                                                            at com.example.findroomies.ui.viewmodels.AuthenticationViewModel$$ExternalSyntheticLambda0.onComplete(Unknown Source:2)
                                                                                                            at com.google.android.gms.tasks.zzi.run(com.google.android.gms:play-services-tasks@@18.0.2:1)
                                                                                                            at android.os.Handler.handleCallback(Handler.java:942)
                                                                                                            at android.os.Handler.dispatchMessage(Handler.java:99)
                                                                                                            at android.os.Looper.loopOnce(Looper.java:201)
                                                                                                            at android.os.Looper.loop(Looper.java:288)
                                                                                                            at android.app.ActivityThread.main(ActivityThread.java:7872)
                                                                                                            at java.lang.reflect.Method.invoke(Native Method)
                                                                                                            at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:548)
                                                                                                            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:936)

можешь поделиться логами ошибок? и синтаксис тоста неверен

Laser 16.05.2024 09:00

@Laser Я добавил для вас журнал ошибок, если это поможет

Ashish 16.05.2024 16:57
1
2
145
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Прежде всего, вы сказали, что у вас проблема в контексте. Таким образом, вы можете решить эту проблему, внедрив контекст приложения в класс viewModel, а затем передав контекст функции в качестве аргумента.

Вот пример для справки. Но все же нужно знать точную причину nullPointerException. Я думаю, вам стоит поделиться журналами ошибок.

@HiltViewModel
class AuthenticationViewModel @Inject constructor(
    private val auth: FirebaseAuth,
    private val toastListner: ToastMessageListener,
    @ApplicationContext private val context: Context
) : ViewModel() {

Затем в своей деятельности вы можете добавить контекст в качестве аргумента.

 override fun showToast(context : Context, message: String) {
        Toast.makeText(context, message, Toast.LENGTH_SHORT).show()
    }

Точно так же вы можете передать этот контекст в класс viewModel.

 toastListner.showToast(context,"Login Failed: ${exception?.message}")

Когда я перемещаю Toast в свой фрагмент, он говорит, что фрагмент не прикреплен к действию. Может ли у меня возникнуть более серьезная проблема? Как можно фрагмент не прикрепить к действию? Возможно, я мог бы решить эту проблему с помощью этого, но можете ли вы помочь мне найти проблему с моим кодом?

Ashish 16.05.2024 17:04

На самом деле вы передали контекст по умолчанию функции всплывающего уведомления в splashActivity, но там нет экземпляра viewModel. Итак, я предполагаю, что вы подключили viewModel к другому фрагменту или действию. Теперь, когда вы вызываете из viewModel, всплывающее сообщение не получает контекст фрагмента или действия, в котором вы находитесь, поскольку вы передали туда контекст по умолчанию.

Laser 17.05.2024 10:42

более того, почему вам нужен интерфейс для отображения тостов? вы можете просто создать функцию расширения и использовать ее где угодно.

Laser 17.05.2024 10:44

Спасибо за объяснение и предложение, думаю, теперь я понимаю лучше.

Ashish 17.05.2024 19:41

не нужно благодарить, просто примите ответ, если он помог. чтобы в будущем это мог прочитать любой желающий.

Laser 18.05.2024 14:11

Другие вопросы по теме