Home > Software design >  How to call api with MVVM in android
How to call api with MVVM in android

Time:09-04

I want call some API from server and for this I used retrofit!
I choose MVVM architecture for my project, I have 2 fragments!
Fragment A and B .
Fragment A : Call APIs and show list in RecyclerView.
Fragment B : Is detail page and show data info.
When tap on back button from device/emulator (in fragment B) and when show Fragment B, again call APIs!
I think when used viewmodel, APIS just call for first time!
I want just call APIs for first time!

Repository class :

class FragmentARepository @Inject constructor(private val api: ApiServices) {

    suspend fun dataList(): Flow<MyResponse<ResponseDataList>> {
        return flow {
            emit(MyResponse.loading())
            emit(MyResponse.success(api.dataList().body()))
        }.catch { emit(MyResponse.error(it.message.toString())) }.flowOn(Dispatchers.Main)
    }
}

ViewModel class :

@HiltViewModel
class FragmentAViewModel @Inject constructor(private val repository: FragmentARepository) : ViewModel() {

    val dalaListLive = MutableLiveData<List<ResponseDataList.Meal>>()
    fun loadDataList() = viewModelScope.launch(Dispatchers.IO) {
        repository.dataList().collect { dataList.postValue(it.body()?.meals!!) }
    }
}

Fragment A class :

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        //InitViews
        binding?.apply {
            viewModel.loadDataList()
            viewModel.dataList.observe(viewLifecycleOwner) {
                dataAdapter.setData(it.data.meals)
                                dataRv.setupRecyclerView(
                                    LinearLayoutManager(requireContext(), LinearLayoutManager.HORIZONTAL, false),
                                    dataAdapter
                                )
                }
            }
}

Why my APIs call every time? I want just one time.
I want just one time.

CodePudding user response:

Your assumption is wrong. ViewModels are not "calling API once". They call API whenever you request them to. In your FragmentA you request data from the view model from onViewCreated, which executes when you re-enter this fragment (e.g, when clicking back from FragmentB)

ViewModel however, is created and is persistent (up to a point): https://developer.android.com/topic/libraries/architecture/viewmodel

So if you want to API call to occur once, you can call it inside your ViewModel's init:

@HiltViewModel
class FragmentAViewModel @Inject constructor(private val repository: FragmentARepository) : ViewModel() {

    val dalaListLive = MutableLiveData<List<ResponseDataList.Meal>>()

    init {
        viewModelScope.launch(Dispatchers.IO) {
        repository.dataList().collect {
            dataList.postValue(it.body()?.meals!!) 
        }
    }
}

And in your FragmentA just observe the dalaListLive:

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        //InitViews
        binding?.apply {
            viewModel.dataList.observe(viewLifecycleOwner) {
                dataAdapter.setData(it.data.meals)
                                dataRv.setupRecyclerView(
                                    LinearLayoutManager(requireContext(), LinearLayoutManager.HORIZONTAL, false),
                                    dataAdapter
                                )
                }
            }
}
  • Related