, поэтому я новичок в 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)
}
}
}
})
}
}
что здесь не так?