androidkotlinretrofit

Data not updating in recycler view after api call using retrofit


I am trying to make a API call and get all data related to orders and show that in a list. I have tested the following which are working as expected.

1 - Adding static data to the view. 2 - The api call is returning the data and is being parsed properly.

The only thing which is not happening is when i am updating the data in the adapter using

orderAdapter!!.notifyDataSetChanged() its not updating the data.

class OrderHistoryActivity : AppCompatActivity() {
    lateinit var recyclerView: RecyclerView
    var orderAdapter: OrderAdapter? = null
    var models: MutableList<OrderModel>? = null
    lateinit var prefs: Prefs

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_order_history)
        recyclerView = findViewById(R.id.orderRecyclerView)
        models = ArrayList()
        prefs = Prefs(this@OrderHistoryActivity)

        GlobalScope.launch(Dispatchers.Default) {
            runCatching {
                Log.d("FUNCTION", "API TO GET ORDERS INIT ${prefs.token} ${prefs.userId}")
                try {
                    val response = withTimeout(REST_API_TIMEOUT) {
                        RetrofitClient(this@OrderHistoryActivity).getApi().getOrders(
                            prefs.token, prefs.userId,"get"
                        ).execute().parseResult<OrdersResponse>()
                    }

                    Log.d("FUNCTION", "API TO GET RESULTS -> RESPONSE ${Gson().toJson(response)} ")
                    response.lastReadDate = System.currentTimeMillis()
                    var i = 0
                     (models as ArrayList<OrderModel>).clear() // CLEAR OLD LIST //
                    while (i < response.data.size) {

                        val data = response.data[i]
                        val order_id=data.id
                        val order_status=data.status
                        val order_date=data.date

                        Log.d("FUNCTION", "API TO GET IND RESULT -> RESPONSE ${order_id} ${order_status}")
                        
                        (models as ArrayList<OrderModel>).add(OrderModel("${order_id}", "Nov 20, 2024", "${order_status}"))
                        i++
                    }

                    // UPDATE DATA //
                    orderAdapter!!.notifyDataSetChanged()

                    Log.d("FUNCTION", "API TO GET IND RESULT MODELS -> RESPONSE ${models}")

                } catch (ex: RestApiException) {
                    var err = OnApiErrorEvent(ex.message ?: ex.toString())
                    Log.d("FUNCTION","rest exp")

                    Log.d("FUNCTIONwwr","${err}")
             
                } catch (ex: Exception) {
                    var err = OnApiErrorEvent(ex.message ?: ex.toString())

                  
                } catch (ex: CancellationException) {


                } finally {

                    launch(Dispatchers.Main) {
//                        viewModel.progress.set(false)
                    }
                }
            }
        }
        for (i in 0..7) {
            (models as ArrayList<OrderModel>).add(OrderModel("#14524$i", "Nov 3, 2022", "Completed"))
        }
        recyclerView.setLayoutManager(LinearLayoutManager(this@OrderHistoryActivity))
        orderAdapter = OrderAdapter(this@OrderHistoryActivity, models)
        recyclerView.setAdapter(orderAdapter)
        Log.d("FUNCTION", "RESULT - > STATIC DATA")


    }

Solution

  • GlobalScope.launch(Dispatchers.Default) {
        runCatching {
            // Your API call and data processing code here...
            
            // Move notifyDataSetChanged inside the Main thread block
            launch(Dispatchers.Main) {
                orderAdapter?.notifyDataSetChanged()
            }
        }
    }
    

    By doing this, you ensure that the adapter is notified of the data change on the main thread, allowing the UI to update properly.

    Additionally, please ensure that you initialize the orderAdapter before making the API call to avoid potential NullPointerException. You can do this by moving the adapter initialization before the API call:

    recyclerView.layoutManager = LinearLayoutManager(this@OrderHistoryActivity)
    

    orderAdapter = OrderAdapter(this@OrderHistoryActivity, models)

    recyclerView.adapter = orderAdapter