Убрать зацикленность, чтобы не нагружать сервер
Я пишу приложение с расписанием моего ВУЗа. Есть API, там есть расписание. Мне надо написать виджет, чтобы расписание выводилось в него в ListView, я что-то написал, оно работает, но я заметил, что на сервер отправляется очень много запросов, поскольку мы по сути вызываем onDataSetChanged в loadDataFromServer и loadDataFromServer в onDataSetChanged. Не совсем желательное поведение, хотелось бы от него избавиться, но я пока что не совсем понимаю как. Хотелось бы добиться такого поведения, чтобы loadDataFromServer вызывался только тогда, когда сам виджет обновляется в соответствии с android:updatePeriodMillis="1800000". Как это можно реализовать и возможно ли вообще?
package com.example.petrsushedule.Widgets
import android.appwidget.AppWidgetManager
import android.appwidget.AppWidgetProvider
import android.content.Context
import android.content.Intent
import android.widget.RemoteViews
import com.example.petrsushedule.R
class MyWidgetProvider : AppWidgetProvider() {
override fun onUpdate(
context: Context,
appWidgetManager: AppWidgetManager,
appWidgetIds: IntArray
) {
val views = RemoteViews(context.packageName, R.layout.full_schedule_widget)
val adapterIntent = Intent(context, FullScheduleService::class.java)
views.setRemoteAdapter(R.id.scheduleListView, adapterIntent)
appWidgetManager.updateAppWidget(appWidgetIds, views)
}
}
package com.example.petrsushedule.Widgets
import android.appwidget.AppWidgetManager
import android.content.ComponentName
import android.content.Context
import android.content.Intent
import android.util.Log
import android.widget.RemoteViews
import android.widget.RemoteViewsService
import com.example.petrsushedule.Interface.ScheduleApi
import com.example.petrsushedule.Model.ScheduleItem
import com.example.petrsushedule.Model.ScheduleResponse
import com.example.petrsushedule.R
import retrofit2.Call
import retrofit2.Callback
import retrofit2.Response
import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory
import java.text.SimpleDateFormat
import java.util.Calendar
class FullScheduleFactory(private val context: Context, intent: Intent) :
RemoteViewsService.RemoteViewsFactory {
private var scheduleList: List<ScheduleItem> = emptyList()
private fun loadDataFromServer() {
val sharedPreferences =
context.getSharedPreferences("MyAppPreferences", Context.MODE_PRIVATE)
val groupNumber = sharedPreferences.getString("userGroup", null)
val appWidgetManager = AppWidgetManager.getInstance(context)
val appWidgetIds = appWidgetManager.getAppWidgetIds(ComponentName(context, MyWidgetProvider::class.java))
if (groupNumber == null) {
Log.d("d", "d")
} else {
val retrofit = Retrofit.Builder()
.baseUrl("https://petrsu.egipti.com/api/v2/")
.addConverterFactory(GsonConverterFactory.create())
.build()
val scheduleApi = retrofit.create(ScheduleApi::class.java)
val scheduleCall = scheduleApi.getScheduleForGroup(groupNumber)
scheduleCall.enqueue(object : Callback<ScheduleResponse> {
override fun onResponse(
call: Call<ScheduleResponse>,
response: Response<ScheduleResponse>
) {
if (response.isSuccessful) {
val scheduleResponse = response.body()
scheduleResponse?.let {
val currentDate = Calendar.getInstance().time
val sdf = SimpleDateFormat("dd.MM.yyyy")
val formattedDate = sdf.format(currentDate)
val sdfTime = SimpleDateFormat("HH:mm")
val formattedTime = sdfTime.format(currentDate)
val todaySchedule =
(scheduleResponse.numerator + scheduleResponse.denominator)
.flatMap {
it.filter { item ->
item.date == formattedDate && item.date.isNotEmpty()
}
}
val nearestFutureSchedule =
(scheduleResponse.numerator + scheduleResponse.denominator)
.firstOrNull { sublist ->
sublist.firstOrNull { it.date > formattedDate } != null
}
val selectedSchedule: List<ScheduleItem>?
if (todaySchedule.isNotEmpty()) {
val lastTodayItem = todaySchedule.last()
selectedSchedule = if (lastTodayItem.start_time.replace(
".",
":"
) < formattedTime
) {
nearestFutureSchedule
} else {
todaySchedule
}
} else {
selectedSchedule = nearestFutureSchedule
}
if (selectedSchedule != null) {
scheduleList = selectedSchedule
}
appWidgetManager.notifyAppWidgetViewDataChanged(appWidgetIds, R.id.scheduleListView)
}
} else {
Log.d("d", "d")
}
}
override fun onFailure(call: Call<ScheduleResponse>, t: Throwable) {
}
})
}
}
override fun onCreate() {}
override fun onDataSetChanged() {
loadDataFromServer()
}
override fun onDestroy() {}
override fun getCount(): Int {
return scheduleList.size
}
override fun getViewAt(position: Int): RemoteViews {
val item = scheduleList[position]
val views = RemoteViews(context.packageName, R.layout.widget_schedule_item_layout)
views.setTextViewText(R.id.lectureStartTime, item.start_time.replace(".", ":"))
views.setTextViewText(R.id.lectureEndTime, item.end_time.replace(".", ":"))
views.setTextViewText(R.id.lectureTitle, item.title)
views.setTextViewText(R.id.lectureType, item.type)
views.setTextViewText(R.id.lecturerName, item.lecturer)
views.setTextViewText(R.id.classroom, item.classroom)
return views
}
override fun getLoadingView(): RemoteViews? {
return null
}
override fun getViewTypeCount(): Int {
return 1
}
override fun getItemId(position: Int): Long {
return position.toLong()
}
override fun hasStableIds(): Boolean {
return true
}
}
package com.example.petrsushedule.Widgets
import android.content.Intent
import android.widget.RemoteViewsService
class FullScheduleService : RemoteViewsService() {
override fun onGetViewFactory(intent: Intent): RemoteViewsFactory {
return FullScheduleFactory(applicationContext, intent)
}
}