0

I am using from MutableLiveData for connect to API, for first time it work true but for second time call twice.(my observe call twice)

Here is my Fragment:

    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View {
     ....
    quizViewModel.getLoginH5P()
    quizViewModel.loginH5P.observe(viewLifecycleOwner) { response ->
        when (response) {
            is Resource.Success -> {
                hideProgressBar()
                response.data?.let {
                    Log.i("MYTAG", "AL " + it.loginurl!!)
                }
            }
            is Resource.Error -> {
                hideProgressBar()
                response.message?.let {
                    Log.i("MYTAG", "AP " + it)
                }
            }

            is Resource.Loading -> {
                showProgressBar()
                Log.i("MYTAG", "AT ")
            }
        }
    }
 .......
}

And Here is My viewModel:

class QuizViewModel(
    private val getQuizUseCase: GetQuizUseCase
) : ViewModel() {
    val loginH5P: MutableLiveData<Resource<LoginH5PEntity>> = MutableLiveData()
    fun getLoginH5P() = viewModelScope.launch(Dispatchers.IO) {
        loginH5P.postValue(Resource.Loading())
        try {
            val apiResult = getQuizUseCase.execute()
            loginH5P.postValue(apiResult)
        } catch (e: Exception) {
            loginH5P.postValue(Resource.Error(e.message.toString()))
        }
    }
}

And here is my impl:

override suspend fun getLoginH5P(): Resource<LoginH5PEntity> {
    return responseToResource(quizRemoteDatasource.getQuiz())
}


private fun responseToResource(response: Response<LoginH5PEntity>): Resource<LoginH5PEntity> {
    if (response.isSuccessful) {
        response.body()?.let { result ->
            return Resource.Success(result)
        }
    }
    return Resource.Error(response.message())
}

And here is my custom Resource:

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

I get my result twice: Log.i("MYTAG", "AL " + it.loginurl!!)

jo jo
  • 1,758
  • 3
  • 20
  • 34

1 Answers1

0

I don't know if this is necessarily the reason for your issue, but you do need to fix it. Your ViewModel has a longer lifespan than the Fragment, but you're re-fetching the data and posting it to the LiveData all over again each time the Fragment recreates the view. You can simply fetch the data once when the ViewModel is created using the liveData builder. The code is simpler using the liveData builder anyway.

class QuizViewModel(
    private val getQuizUseCase: GetQuizUseCase
) : ViewModel() {
    val loginH5P: LiveData<Resource<LoginH5PEntity>> = liveData {
        emit(Resource.Loading())
        try {
            emit(getQuizUseCase.execute())
        } catch (e: Exception) {
            emit(Resource.Error(e.message.toString()))
        }
    }
}
Tenfour04
  • 83,111
  • 11
  • 94
  • 154
  • It good work now, but I need call API when I coming to fragment. It just call API just once, when I coming to fragment don't call it again. – jo jo Aug 29 '22 at 08:20
  • How are you getting your ViewModel reference? Using the Activity (a shared ViewModel)? – Tenfour04 Aug 29 '22 at 08:24
  • I am using from BottomNavigationView in Activity. – jo jo Aug 29 '22 at 09:10
  • I Edited your response like bellow and it good work now.(you can edit your response and I accepted it). In viewModel: fun loginH5Pd() = liveData { emit(Resource.Loading()) try { emit(getQuizUseCase.execute()) } catch (e: Exception) { emit(Resource.Error(e.message.toString())) } } – jo jo Aug 29 '22 at 09:23
  • And in fragment: val responseLiveData = quizViewModel.loginH5Pd() responseLiveData.observe(activity!!, Observer { when (it) { is Resource.Success -> { hideProgressBar() it.data?.let { } } is Resource.Error -> { hideProgressBar() it.message?.let { } } is Resource.Loading -> { showProgressBar() } } }) – jo jo Aug 29 '22 at 09:24