0

I am using Jetpack navigation component. I have a list with pagination and with same list I am populating map markers. I am using live data with view model. I am observing with viewLifecycleOwner. As per jetpack navigation component, fragment will replace not add, so my fragment onViewCreated called whenever I switch from Fragment A to B, due to this all marker render heavy operations called again.

I tried in view model with viewModelScope.launch {} but the result is same.

The last thing which is working for me is: I defined a bool for this firsTime. So I started observing when firstTime flag is true, once observer is set I called this flag to false and this is preventing this heavy operation again and again.

So question is: setting flag is fine? or is there is any other better solution.

My View Model:

val gymBuddiesPagingLiveData: MutableLiveData<ViewStatePaging<MutableList<SingleGymBuddyItem>>> = MutableLiveData<ViewStatePaging<MutableList<SingleGymBuddyItem>>>()
    private val localPagingGymBuddiesMobile: MutableList<SingleGymBuddyItem> = mutableListOf()
    private var gymBuddiesPage = 1

    
    suspend fun getPageGymBuddiesMobile(gymBuddyFilter: GymBuddiesFilter){
        viewModelScope.launch {


            if(gymBuddiesPage == 1){
                gymBuddiesPagingLiveData.postValue(ViewStatePaging.FirstPage())
            }
            else{
                gymBuddiesPagingLiveData.postValue(ViewStatePaging.Loading())
            }
           val page = PaginatorInput(gymBuddiesPage, PAGING_LIMIT)




            homeRepository.getGymBuddiesMobile(page, gymBuddyFilter).collect {
                when (it) {
                    is Resource.Success -> {
                        gymBuddiesPage++

                        val data = it.data.gymBuddiesMobile.list?.map {

                            SingleGymBuddyItem(
                                it
                            )
                        }

                        if(localPagingGymBuddiesMobile.isEmpty() && (data?.isEmpty() == true)){
                            gymBuddiesPagingLiveData.value = ViewStatePaging.NoResult()
                        }
                        else{
                            if(!data.isNullOrEmpty()){
                                localPagingGymBuddiesMobile.addAll(data)
                                gymBuddiesPagingLiveData.value = ViewStatePaging.Success(localPagingGymBuddiesMobile)

                                //pagingGymBuddiesMarkers.addAll(transformGymBuddyMarkers(data))
                                //gymBuddiesMarkersLiveData.value = pagingGymBuddiesMarkers
                            }
                            else{
                                gymBuddiesPagingLiveData.value = ViewStatePaging.LastPage()
                            }
                        }



                    }
                    is Resource.Failed -> {
                        gymBuddiesPagingLiveData.value = ViewStatePaging.Error(it.message)
                    }
                }
            }

        }
    }

And here is my observer in fragment:

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
observeEvents()
}



private fun observeEvents() {
        mViewModel.events.observe(viewLifecycleOwner) { response ->
            when(response) {
                is ViewState.Loading -> {
                    binding.progressEvent.visible()
                    binding.noItemFoundTv.gone()
                }
                is ViewState.Error -> {
                    setNoDataView()
                }
                is ViewState.Success -> {
                    binding.noItemFoundTv.gone()
                    if(response.value.isNullOrEmpty()){
                        setNoDataView()
                    }
                    else{

                        listEvents.clear()
                        listEvents.addAll(response.value!!)
                        listAdapter.addAll(listEvents)
                        homeAdapter.addAll(listEvents.filter { it.type == 2 })
                        setDataView()

                        val mapList = mutableListOf<SingleEvent>()
                        listEvents.forEach {
                            if(it.type == 2){
                                it.singleEvent?.let { it1 -> mapList.add(it1) }
                            }
                        }

                        if(markersOrderNumbers.size != mapList.size){
                            populateMarkers(mapList)
                        }

                        mapOperations()

                    }
                }
            }

        }
    }
Ziaullah
  • 65
  • 2
  • 6
  • `onViewCreated` should be called whenever the fragment needs to create its view - when you navigate to fragment or navigate back to it. is this your case? – Shlomi Katriel Sep 08 '22 at 06:26
  • Yes @ShlomiKatriel you got correct. This is my case. – Ziaullah Sep 08 '22 at 06:31
  • 1
    So it makes sense to me - the fragment actually needs to draw itself to the screen. either this or I misunderstood the question :) – Shlomi Katriel Sep 08 '22 at 06:44
  • why are you replacing the fragment if you don't want to re-draw, did you try to add instead of replacing the fragment in the stack? – vVv Sep 08 '22 at 07:26
  • 1
    Adding to what @ShlomiKatriel said, it is hard to know where you are observing/triggering the data from. Add some code so we can help with avoiding re-fetching it every time the Fragment is recreated. – gioravered Sep 08 '22 at 07:41
  • I can't see where you are calling getPageGymBuddiesMobile. But if you want to to happen a single time you can call it inside the ViewModel's init method and make the Fragment only observe the LiveData. This might help: https://stackoverflow.com/questions/73596858/how-to-call-api-with-mvvm-in-android – gioravered Sep 08 '22 at 10:57
  • Yes I did in view model init. Api not calling twice, the issue is the map marker list draw again and again, I don't have any diff utill in map fragment, may be map cluster should be use full in this case, but I am not going to implement map clustering right now. So due to view recreation markers draw again and again, although I prevent this by flag, but this is not a good solutiion @gioravered – Ziaullah Sep 08 '22 at 11:53

0 Answers0