各位大大,小弟最近正在練習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
}