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

Issue

I have some errors in Retrofit2 and Kotlin Coroutines technologies. I need to dynamically query an info in my service.

For example, the URL is "https://exampleapidomain.com/api/sub_categories/read.php?id=2" I want to change id parameter dynamically.

My service:

interface AltKategoriService {

    @GET("alt_kategoriler/" + Const.READ_URL_PIECE)
    fun getId(@Query("id") id: String?): Call<Resource<AltKategorilerResponse>>

    companion object{
        fun build(): AltKategoriService {
            val interceptor = HttpLoggingInterceptor()
            interceptor.level = HttpLoggingInterceptor.Level.BODY

            val okHttpClient = OkHttpClient.Builder()
                .addInterceptor(interceptor)
                .build()

            val retrofit = Retrofit.Builder()
                .addConverterFactory(GsonConverterFactory.create())
                .baseUrl(Const.BASE_URL)
                .client(okHttpClient)
                .build()

            return retrofit.create(AltKategoriService::class.java)
        }
    }
}

My DataSource file:

class RemoteAltKategorilerDataSource : AltKategorilerDataSource {
    override fun getSubCategories(): Flow<Resource<AltKategorilerResponse>> = flow {
        try {
            emit(Resource.Loading())

            val call = AltKategoriService.build().getId("2").execute()
            if (call.isSuccessful) {

                call.body()?.let {
                    emit(it)
                }
            }

        } catch (ex: Exception) {
            emit(Resource.Error(ex))
            ex.printStackTrace()
        }
    }
}

I get the following error:

Attempt to invoke virtual method 'void androidx.lifecycle.MutableLiveData.postValue(java.lang.Object)' on a null object reference" and then, app crashes.

I’m waiting for your answers and code examples. Thank you!

Edited. My ViewModel:

class SubCategoryViewModel: ViewModel() {
    private val altKategoriRepository = AltKategoriRepository()

    init {
        getUsers()
    }

    var loading: MutableLiveData<Boolean>? = MutableLiveData()
    var altKategoriLiveData = MutableLiveData<AltKategorilerResponse>()
    var error = MutableLiveData<Throwable>()

    fun getUsers() = viewModelScope.launch {
        altKategoriRepository.getSubCategories()
            .asLiveData(viewModelScope.coroutineContext).observeForever {

                when (it.status) {
                    ResourceStatus.LOADING -> {
                        loading?.postValue(true)
                    }

                    ResourceStatus.SUCCESS -> {
                        Log.e("Message", it.data.toString())
                        altKategoriLiveData.postValue(it.data!!)
                        loading?.postValue(false)
                    }

                    ResourceStatus.ERROR -> {
                        error.postValue(it.throwable!!)
                        loading?.postValue(false)
                    }
                }
            }
    }
}

Solution

Kotlin class initialisation takes place in the following order:

primary constructor -> init block -> secondary constructor

As no initialisation is done neither for var loading, var altKategoriLiveData nor var error class members of SubCategoryViewModel by the time getUsers() is called in the init { } block, you get the exception resulting in the app crash.

Regarding your implementation of the MVVM pattern, it contradicts to that of the official Android documentation, where a View is supposed to call a corresponding method of ViewModel explicitly or implicitly.

Answered By – Onik

This Answer collected from stackoverflow, is licensed under cc by-sa 2.5 , cc by-sa 3.0 and cc by-sa 4.0

Leave a Reply

(*) Required, Your email will not be published