почему, когда я добавляю данные в адаптер, это также меняет мои LiveData? - PullRequest
0 голосов
/ 11 марта 2020

, поэтому я новичок в MVVM, используя компонент архитектуры. Я хочу добавить нижний колонтитул загрузки в моем представлении переработчика. После добавления фиктивного элемента в адаптер, чтобы показать загрузочный нижний колонтитул в моем адаптере, я не понимаю, почему этот фиктивный элемент (ресторан) также появляется в моем потоке LiveData (в моем репозитории и RestaurantClient из модернизации), я предполагаю, что нет никакого соединения между адаптером и моим потоком LiveData

вот мой адаптер

class RestaurantRecyclerAdapter(var mOnItemClickedListener : OnItemClickedListener): RecyclerView.Adapter<RecyclerView.ViewHolder>() {


    private val ITEM_TYPE = 0
    private val LOADING_TYPE = 1

    var restaurantList =  ArrayList<Restaurant>()

    override fun getItemViewType(position: Int): Int {
        if ( restaurantList[position].name == "dummy" ) {
            return LOADING_TYPE
        } else {
            return ITEM_TYPE
        }
    }




    fun addLoadingFooter() {

        if (!isLoading) {
            isLoading = true

            val dummyRestaurant = Restaurant()
            dummyRestaurant.name = "dummy"
            restaurantList.add(dummyRestaurant)
            notifyDataSetChanged()
        }
    }

    fun removeLoadingFooter() {

        isLoading = false

        val index = restaurantList.indexOfFirst{
            it.name == "dummy"
        }

        if (index != -1) {
            restaurantList.removeAt(index)
            notifyDataSetChanged()
        }


    }

когда представление рециркулятора достигнет дна, он будет запускать этот код для повторного получения данных с сервера, вот также мой наблюдатель список в моем фрагменте

class RestaurantListFragment : Fragment(), OnItemClickedListener {

    lateinit var model : RestaurantListViewModel
    lateinit var restaurantRecyclerAdapter: RestaurantRecyclerAdapter


    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        // Inflate the layout for this fragment

        fragmentView = inflater.inflate(R.layout.fragment_restaurant_list, container, false)
        model = ViewModelProvider(this).get(RestaurantListViewModel::class.java)

        recyclerView.addOnScrollListener(object : RecyclerView.OnScrollListener() {

            override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) {
                super.onScrollStateChanged(recyclerView, newState)

                val isLoading = model.isLoading.value ?: return
                val isQueryExhausted = model.isQueryHausted.value ?: return


                if (!recyclerView.canScrollVertically(1) && !isLoading && !isQueryExhausted) {

                    model.searchNextPage() 
                    restaurantRecyclerAdapter.addLoadingFooter() // <-- add footer in here
                }
            }

        })


        model.restaurants.observe(viewLifecycleOwner, Observer { restaurantList ->

            // that dummy restaurant object I add from adapter to show loading footer
            // will also show in my LiveData in 'restaurantList' in here


            restaurantList?.let {

                restaurantRecyclerAdapter.setRestaurants(it)
                restaurantRecyclerAdapter.removeLoadingFooter() // remove footer in here
                showLoadingIndicator(false)

            }

        })


        return fragmentView
    }


}

вот viewModel для этого фрагмента

class RestaurantListViewModel : ViewModel() {

    var restaurants : LiveData<ArrayList<Restaurant>> = RestaurantRepository.restaurants

    fun searchRestaurants(query: String) {


        RestaurantRepository.searchRestaurants(
            query = query,
            latitude = mLatitude,
            longitude = mLongitude
        )
    }

    fun searchNextPage() {

        RestaurantRepository.searchNextPage(mLatitude,mLongitude)

    }




}

здесь мой репозиторий

object RestaurantRepository {

    val restaurants: MediatorLiveData<ArrayList<Restaurant>> = MediatorLiveData()
    private val restaurantsFromClient : LiveData<ArrayList<Restaurant>> = RestaurantClient.restaurants

    init {
        initMediators()
    }

    private fun initMediators() {

        restaurants.addSource(restaurantsFromClient) { restaurantList ->

            if (restaurantList == null) {
                // get data from Room database
            } else {
                restaurants.postValue(restaurantList)
            }


        }

    }


    fun searchNextPage(latitude:Double, longitude: Double) {

        val numberOfCurrentShowedRestaurants = restaurants.value?.size ?: return

        RestaurantClient.searchRestaurants(
            query = mQuery,
            latitude = latitude,
            longitude = longitude,
            start = numberOfCurrentShowedRestaurants + NUMBER_OF_DOCUMENT_PER_PAGE
        )



    }

}

и вот клиент ресторана для получения данные с сервера с использованием модернизации

object RestaurantClient {

    val restaurants = MutableLiveData<ArrayList<Restaurant>>()

    private val restaurantService = RetrofitServiceGenerator.getInstance(RestaurantAPI::class.java)

    fun searchRestaurants(query: String, latitude:Double, longitude: Double, start: Int) {

        val call = restaurantService.searchRestaurants(
            radius = 2000,
            query = query,
            latitude = latitude,
            longitude = longitude,
            start = start,
            count = NUMBER_OF_DOCUMENT_PER_PAGE
        )

        isLoading.value = true

        call.enqueue(object: Callback<RestaurantListBaseResponse> {

            override fun onFailure(call: Call<RestaurantListBaseResponse>, t: Throwable) {

            }

            override fun onResponse(call: Call<RestaurantListBaseResponse>, response: Response<RestaurantListBaseResponse>) {

                isLoading.postValue(false)

                if (response.isSuccessful) {

                    val bodyResponse = response.body() ?: return

                    val listOfRestaurants = bodyResponse.restaurants
                    val restos = ArrayList<Restaurant>()

                    for (i in listOfRestaurants ) {
                        restos.add(i.restaurant)
                    }


                    if (start == 0) {
                        restaurants.postValue(restos)

                    } else {
                        restaurants.value?.let {
                            val newRestaurants = it

                            for (i in listOfRestaurants ) {
                                newRestaurants.add(i.restaurant)
                            }

                            restaurants.postValue(newRestaurants)

                        }

                    }


            }

        })


    }




}

что здесь не так?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...