iT邦幫忙

0

使用viewmodel背景更新RecyclerView的API數據列表,但是notifyDataSetChanged()無動作問題

  • 分享至 

  • xImage

各位大大,小弟最近正在練習android的MVVM的架構用請求API的資料更新RecycleView的列表.但是小弟遇到了問題,用viewModel做非同步的每10秒請求一次API,而Adapter的notifyDataSetChanged()的韓式都不會動作,小弟都有確認Model都有請請求API收到數據,希望大大能幫忙小弟看壹下問題出在哪,以下這是我的程式碼:
要抓的API:https://www.kia.gov.tw/API/InstantSchedule.ashx?AirFlyLine=2&AirFlyIO=2

Model:

class FlightRepository {

    fun fetchFlights(callback: (List<FlightInfo>?) -> Unit) {

        flightApi.getFlights().enqueue(object : Callback<FlightResponse> {
            override fun onResponse(
                call: Call<FlightResponse>,
                response: Response<FlightResponse>
            ) {
                if (response.isSuccessful) {
                    val flights = response.body()?.InstantSchedule ?: emptyList()
                    callback(flights)
                } else {
                    callback(emptyList())  // 失敗時回傳空列表

                    _error.value = "API 回應錯誤: ${response.code()}"
                    Log.d(
                        "response.isSuccessful:",
                        response.isSuccessful.toString() + " " + _error.value
                    )
                }
            }
            override fun onFailure(call: Call<FlightResponse>, t: Throwable) {
                callback(emptyList())
                Log.d("response.isSuccessful:", t.printStackTrace().toString())
            }

        })
    }
}

ViewModel:

class FlightViewModel : ViewModel() {
    private val repository = FlightRepository()
    private val _flights = MutableLiveData<List<FlightInfo>?>()
    val flights: LiveData<List<FlightInfo>?> get() = _flights

    private var updateJob: Job? = null

    init {
        startAutoUpdate()// 啟動 10 秒自動更新
    }

     fun loadFlights() {
        repository.fetchFlights { data ->

            if(data != null){
                _flights.postValue(data ?: emptyList())
                Log.d("FlightViewModel", "loadFlights data: "+data)
            }

        }
    }

    fun startAutoUpdate(intervalMillis: Long = 10000L) {

        if(updateJob?.isActive==true) return// 確保不重複啟動

        updateJob = viewModelScope.launch {

            while (isActive) {

                try {
                    loadFlights()
                    //val data=repository.

                    delay(intervalMillis)
                } catch (e: Exception) {

                    Log.e("FlightViewModel", "Fetch error: ${e.message}")
                }

                Log.d("FlightViewModel", "OKOKOK")

            }
        }

    }

View(主要監聽viewmodel):

class FlightViewModel : ViewModel() {

    private val repository = FlightRepository()
    private val _flights = MutableLiveData<List<FlightInfo>?>()
    val flights: LiveData<List<FlightInfo>?> get() = _flights

    private var updateJob: Job? = null

    init {
        startAutoUpdate()// 啟動 10 秒自動更新
    }

     fun loadFlights() {
        repository.fetchFlights { data ->

            if(data != null){
                _flights.postValue(data ?: emptyList())
                Log.d("FlightViewModel", "loadFlights data: "+data)
            }

        }
    }

    fun startAutoUpdate(intervalMillis: Long = 10000L) {

        if(updateJob?.isActive==true) return// 確保不重複啟動

        updateJob = viewModelScope.launch {

            while (isActive) {

                try {
                    loadFlights()
                    //val data=repository.

                    delay(intervalMillis)
                } catch (e: Exception) {

                    Log.e("FlightViewModel", "Fetch error: ${e.message}")
                }

                Log.d("FlightViewModel", "OKOKOK")

            }
        }

    }

RecycleViewAdapter:

class FlightRecyclerViewAdapter :
    RecyclerView.Adapter<FlightRecyclerViewAdapter.FlightViewHolder>() {
    private var flightList: List<FlightInfo> = emptyList()
    class FlightViewHolder(private val binding: ItemFlightBinding) :
        RecyclerView.ViewHolder(binding.root) {

        fun bind(datas: FlightInfo) {

            binding.AirLineNum.text = "航機班號: ${datas.airLineNum}"
            binding.ExpectTime.text = datas.expectTime
            binding.RealTime.text = datas.realTime
            binding.BoardingGate.text = "航廈/登機門: ${datas.airBoardingGate}"
            binding.upAirportName.text = datas.upAirportName
            binding.AirFlyStatus.text = "航機狀態: ${datas.airFlyStatus}"

            Glide.with(itemView.context)
                .load(datas.airLineLogo ?: R.drawable.ic_launcher_foreground)
                .into(binding.AirLogo)
        }
    }

   fun updateData(data: List<FlightInfo>) {

        flightList = data.toMutableList()
        Log.d("FlightRecyclerViewAdapter","data"+data)
        notifyDataSetChanged()//沒有動作
    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): FlightViewHolder {
        var inflater = LayoutInflater.from(parent.context)
        var binding = ItemFlightBinding.inflate(inflater, parent, false)

        return FlightViewHolder(binding)
    }

    override fun onBindViewHolder(holder: FlightViewHolder, position: Int) {
        holder.bind(flightList[position])
    }

    override fun getItemCount(): Int = flightList.size
}
.

尚未有邦友回答

立即登入回答