Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

java.lang.NullPointerException:Attempt to invoke virtual method 'void androidx.lifecycle.MutableLiveData.postValue(java.lang.Object)' on a null object

My ViewModel class

@HiltViewModel
class RandomRecipeViewModel @Inject constructor(
    val repo: RecipesRepo,
    val app: MyApplication
) : AndroidViewModel(app) {
    init {
        getRandomRecipes()
    }

    val randomRecipe = MutableLiveData<Resource<RandomRecipe>>()
    var randomRecipeList: RandomRecipe? = null

    fun getRandomRecipes() {
        viewModelScope.launch {

            try {
                **//Exception in the below line**
                randomRecipe.postValue(Resource.Loading())
                val response = repo.getRandomRecipes()
                randomRecipe.postValue(handleRandomRecipeResponse(response))          
            } catch (e: Throwable) {
                if (e is IOException) {
                    randomRecipe.postValue(Resource.Error("Turn on Internet"))
                } else {
                    randomRecipe.postValue(Resource.Error("Conversion Problem"))
                }
            }
        }
    }

    private fun handleRandomRecipeResponse(response: Response<RandomRecipe>): Resource<RandomRecipe> {
        if(response.isSuccessful) {
            response.body()?.let { newResponse->
                if(randomRecipeList == null) {
                    randomRecipeList = newResponse
                }else{
                    val oldRecipeList = randomRecipeList?.recipes
                    val newRecipeList = newResponse.recipes

                    oldRecipeList?.addAll(newRecipeList)
                }
                return Resource.Success(randomRecipeList ?: newResponse)
            }
        }
        return Resource.Error(msg = response.message())
    }
}

RandomRecipe(MainActivity)

@AndroidEntryPoint
class RandomRecipes : AppCompatActivity() {
    private lateinit var binding: RecipesRandomBinding
    lateinit var randomRecipeViewModel: RandomRecipeViewModel

    lateinit var randomRecipeAdapter: RandomRecipeAdapter

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = RecipesRandomBinding.inflate(layoutInflater)
        setContentView(binding.root)

        supportActionBar?.hide()
        randomRecipeAdapter = RandomRecipeAdapter()
        randomRecipeViewModel = ViewModelProvider(this)[RandomRecipeViewModel::class.java]

        binding.apply {
            randomRecyclerView.adapter = randomRecipeAdapter
            randomRecyclerView.layoutManager = LinearLayoutManager(applicationContext)
        }


        randomRecipeViewModel.randomRecipe.observe(this, Observer { resource->
            when(resource) {
                is Resource.Loading -> showProgressBar()
                is Resource.Error -> {
                    hideProgressBar()
                    resource.msg?.let {
                        Snackbar.make(binding.randomRecipeActivity, it, Snackbar.LENGTH_INDEFINITE)
                            .setAction("Refresh"){
                                randomRecipeViewModel.getRandomRecipes()
                            }.show()
                    }
                }
                is Resource.Success -> {
                    hideProgressBar()
                    resource.data?.let {  recipe ->
                        randomRecipeAdapter.differ.submitList(recipe.recipes.toList())
                    }
                }
            }
        })
    }
    private fun showProgressBar() {
        binding.progressbar.visibility = View.VISIBLE
    }
    private fun hideProgressBar() {
        binding.progressbar.visibility = View.INVISIBLE
    }
}

Resource class

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

    sealed class Resource<T>(
    val data: T? = null,
    val msg: String? = null
) {
    class Loading<T>(): Resource<T>()
    class Success<T>(data: T): Resource<T>(data)
    class Error<T>(msg: String, data: T? = null): Resource<T>(data, msg)
}

Error
java.lang.NullPointerException: Attempt to invoke virtual method ‘void androidx.lifecycle.MutableLiveData.postValue(java.lang.Object)’ on a null object reference
at com.example.recipe.viewmodels.RandomRecipeViewModel$getRandomRecipes$1.invokeSuspend(RandomRecipeViewModel.kt:45)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
at kotlinx.coroutines.internal.DispatchedContinuationKt.resumeCancellableWith(DispatchedContinuation.kt:367)
at kotlinx.coroutines.intrinsics.CancellableKt.startCoroutineCancellable(Cancellable.kt:30)
at kotlinx.coroutines.intrinsics.CancellableKt.startCoroutineCancellable$default(Cancellable.kt:25)
at kotlinx.coroutines.CoroutineStart.invoke(CoroutineStart.kt:110)
at kotlinx.coroutines.AbstractCoroutine.start(AbstractCoroutine.kt:126)
at kotlinx.coroutines.BuildersKt__Builders_commonKt.launch(Builders.common.kt:56)
at kotlinx.coroutines.BuildersKt.launch(Unknown Source:1)
at kotlinx.coroutines.BuildersKt__Builders_commonKt.launch$default(Builders.common.kt:47)
at kotlinx.coroutines.BuildersKt.launch$default(Unknown Source:1)
at com.example.recipe.viewmodels.RandomRecipeViewModel.getRandomRecipes(RandomRecipeViewModel.kt:33)
at com.example.recipe.viewmodels.RandomRecipeViewModel.(RandomRecipeViewModel.kt:26)
at com.example.recipe.util.DaggerMyApplication_HiltComponents_SingletonC$ViewModelCImpl.randomRecipeViewModel(DaggerMyApplication_HiltComponents_SingletonC.java:442)
at com.example.recipe.util.DaggerMyApplication_HiltComponents_SingletonC$ViewModelCImpl.access$1800(DaggerMyApplication_HiltComponents_SingletonC.java:419)
at com.example.recipe.util.DaggerMyApplication_HiltComponents_SingletonC$ViewModelCImpl$SwitchingProvider.get(DaggerMyApplication_HiltComponents_SingletonC.java:477)
at dagger.hilt.android.internal.lifecycle.HiltViewModelFactory$1.create(HiltViewModelFactory.java:100)
at androidx.lifecycle.AbstractSavedStateViewModelFactory.create(AbstractSavedStateViewModelFactory.java:97)
at androidx.lifecycle.AbstractSavedStateViewModelFactory.create(AbstractSavedStateViewModelFactory.java:119)
at dagger.hilt.android.internal.lifecycle.HiltViewModelFactory.create(HiltViewModelFactory.java:109)
at androidx.lifecycle.ViewModelProvider$Factory.create(ViewModelProvider.kt:83)
at androidx.lifecycle.ViewModelProvider.get(ViewModelProvider.kt:187)
at androidx.lifecycle.ViewModelProvider.get(ViewModelProvider.kt:153)
at com.example.recipe.RandomRecipes.onCreate(RandomRecipes.kt:31)
at android.app.Activity.performCreate(Activity.java:7088)
at android.app.Activity.performCreate(Activity.java:7079)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1215)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2770)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2895)
at android.app.ActivityThread.-wrap11(Unknown Source:0)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1616)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loop(Looper.java:176)
at android.app.ActivityThread.main(ActivityThread.java:6651)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:547)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:824)

>Solution :

Switch the order of the init block and property initializers:

val randomRecipe = MutableLiveData<Resource<RandomRecipe>>()
var randomRecipeList: RandomRecipe? = null

init {
    getRandomRecipes()
}

Kotlin documentation is pretty clear on that topic:

During the initialization of an instance, the initializer blocks are executed in the same order as they appear in the class body, interleaved with the property initializers.

The randomRecipe was simply not initialized at the time when the getRandomRecipes method was executed.

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading