androidkotlinandroid-recyclerviewretrofitnotifydatasetchanged

notifyDataSetChanged() is not working after fetching data with Retrofit and DisposableSingleObserver


I've been trying to solve this problem for over 3 hours. Everything seems just fine on the Logcat and Debug mode. I'm fetching the List without any problem, Fragment is reading the MutableLiveData successfully. Only the notifyDataSetChanged() function is not working and also it doesn't give any error etc. If I send an ArrayList manually then it works but if it goes inside Retrofit and DisposableSingleObserver then even the manual list doesn't work.

I have tried every way that I could have found on the internet. I've looked for more than 20 different solution none of them have worked.

API - HoroscopeAPI.kt

interface HoroscopeAPI {
@GET("astraios/horoscopeList.json")
fun getHoroscope(): Single<List<Horoscope>>
}

Service - HoroscopeAPIService.kt

class HoroscopeAPIService {
private val BASE_URL = "https://wiuma.co"
private val api = Retrofit.Builder()
    .baseUrl(BASE_URL)
    .addConverterFactory(GsonConverterFactory.create())
    .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
    .build()
    .create(HoroscopeAPI::class.java)

fun getData(): Single<List<Horoscope>> {
    return api.getHoroscope()
}
}

ViewModel - HoroscopeViewModel.kt

class HoroscopeViewModel : ViewModel() {
private val horoscopeApiService = HoroscopeAPIService()
private val disposable = CompositeDisposable()
val horoscopeList = MutableLiveData<List<Horoscope>>()

fun getDataFromAPI() {
    loadingStatus.value = true
    disposable.add(
        horoscopeApiService.getData()
            .subscribeOn(Schedulers.newThread())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribeWith(object : DisposableSingleObserver<List<Horoscope>>() {
                override fun onSuccess(t: List<Horoscope>) {
                    horoscopeList.value = t
                }
                override fun onError(e: Throwable) {
                    e.printStackTrace()
                }
            })
    )
}
}

Fragment - Horoscope.kt

override fun onCreateView(
    inflater: LayoutInflater,
    container: ViewGroup?,
    savedInstanceState: Bundle?
): View? {
    horoscopeViewModel =
        ViewModelProvider(this).get(HoroscopeViewModel::class.java)
    val root = inflater.inflate(R.layout.fragment_horoscope, container, false)
    horoscopeViewModel.getDataFromAPI()
    horoscopeRecyclerView = root.findViewById(R.id.horoscopeRecyclerView)
    horoscopeRecyclerView.layoutManager = LinearLayoutManager(context)
    horoscopeRecyclerView.adapter = recyclerViewAdapter
    observeData()
    return root
}

fun observeData() {
    horoscopeViewModel.horoscopeList.observe(viewLifecycleOwner, Observer { horoscope ->
        horoscope?.let {
            recyclerViewAdapter.updateList(horoscope)
        }
    })}

**Adapter - HoroscopeRecyclerAdapter.kt **

class HoroscopeRecyclerAdapter(val horoscopeList: ArrayList<Horoscope>) :
RecyclerView.Adapter<HoroscopeRecyclerAdapter.HoroscopeViewHolder>() {
class HoroscopeViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {

}

override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): HoroscopeViewHolder {
    val inflater = LayoutInflater.from(parent.context)
    val view = inflater.inflate(R.layout.horoscope_recycler_row, parent, false)
    return HoroscopeViewHolder(view)
}

@SuppressLint("SetTextI18n")
override fun onBindViewHolder(holder: HoroscopeViewHolder, position: Int) {
    holder.itemView.horoscopeName.text = horoscopeList.get(position).nameHoroscope
    holder.itemView.horoscopeDates.text =
        horoscopeList.get(position).startDate + " " + horoscopeList.get(position).endDate
    //TODO Gorsel baglantisi eklenecek.

    holder.itemView.setOnClickListener {
        val action =
            HoroscopeFragmentDirections.actionNavigationHoroscopeToNavigationHoroscopeDetails(0)
        Navigation.findNavController(it).navigate(action)
    }
}

override fun getItemCount(): Int {
    return horoscopeList.size
}

fun updateList(newHoroscopeList: List<Horoscope>) {
    horoscopeList.clear()
    horoscopeList.addAll(newHoroscopeList)
    notifyDataSetChanged()
}}

Solution

  • I ran your project from Github. notifyDataSetChanged() seems to be working fine. The reason why the list items aren't showing up is that the visibility of the RecyclerView is set to GONE. It needs to be set back to VISIBLE when the results arrive:

        fun observeData() {
            horoscopeViewModel.horoscopeList.observe(viewLifecycleOwner, Observer { horoscope ->
                horoscope?.let {
                    errorText.visibility = View.GONE
                    progressBar.visibility = View.GONE
                    horoscopeRecyclerView.visibility = View.VISIBLE
                    recyclerViewAdapter.updateList(it)
                }
            })