Віджет цени криптовалюти для Home Screen (iOS та Android)
Віджет на головному екрані — це окремий процес, що живе незалежно від основного додатку. Це не компонент усередину додатку і не фоновий сервіс з доступом до мережі в будь-який момент. На iOS це WidgetKit + SwiftUI, на Android — Jetpack Glance або класичний AppWidgetProvider. Обидва працюють за принципом snapshot: система запитує актуальний UI у певні моменти, і те, що відобразиться — ваша відповідальність.
iOS: WidgetKit та обмеження оновлень
WidgetKit не дозволяє віджету робити мережеві запити в реальному часі. Віджет отримує дані через TimelineProvider, який повертає масив TimelineEntry з заздалегідь підготованими даними та часовими мітками. Система сама вирішує, коли перерисувати віджет.
Для крипто-віджета типова стратегія — оновлення кожні 15–30 хвилин через TimelineReloadPolicy.atEnd або .after(date:):
struct CryptoPriceEntry: TimelineEntry {
let date: Date
let symbol: String
let price: Decimal
let change24h: Double
}
struct CryptoPriceProvider: TimelineProvider {
func getTimeline(in context: Context,
completion: @escaping (Timeline<CryptoPriceEntry>) -> Void) {
Task {
let price = try? await CryptoAPIClient.shared.fetchPrice(symbol: "BTC")
let entry = CryptoPriceEntry(date: .now,
symbol: "BTC",
price: price?.usd ?? 0,
change24h: price?.change24h ?? 0)
let nextUpdate = Calendar.current.date(byAdding: .minute, value: 15, to: .now)!
let timeline = Timeline(entries: [entry], policy: .after(nextUpdate))
completion(timeline)
}
}
}
Важливий нюанс: Apple регулює бюджет оновлень. Віджет з високою частотою оновлень на пристроях з низьким зарядом батареї отримує урізаний бюджет — оновлення починають приходити рідше, ніж запрошено. Для трейдинг-додатків з вимогою «дані не старіше 1 хвилини» WidgetKit підходить погано — потрібно чесно пояснити це клієнту перед початком розробки.
Передача даних між основним додатком і віджетом — через App Groups + UserDefaults(suiteName:) або FileManager з shared container. @AppStorage усередину віджета працює тільки з App Group suite — без цього віджет не побачить дані, записані основним додатком.
Розміри та адаптація UI
WidgetKit підтримує 4 розміри: .systemSmall, .systemMedium, .systemLarge, .systemExtraLarge (тільки iPad). Для крипто-віджета звичайно робимо small (символ + ціна + зміна) та medium (кілька монет в рядок). SwiftUI у віджеті не підтримує анімацій, ScrollView, клацань на довільні області — тільки Link для deep link.
Android: Jetpack Glance
Jetpack Glance — Compose-подібний API для віджетів, з'явився у 2022 році. Помітно зручніше класичного RemoteViews, але має обмеження: підтримуються не всі Compose-модифікатори, а частина API працює інакше, ніж у звичайному Compose.
Оновлення даних через GlanceAppWidgetManager.updateIf + WorkManager з періодичною задачею:
class CryptoPriceWidget : GlanceAppWidget() {
override suspend fun provideGlance(context: Context, id: GlanceId) {
val prefs = currentState<Preferences>()
val price = prefs[priceKey] ?: "—"
val change = prefs[changeKey] ?: "0.0"
provideContent {
Column(
modifier = GlanceModifier.fillMaxSize().background(Color.DarkGray).padding(12.dp)
) {
Text("BTC", style = TextStyle(color = ColorProvider(Color.White), fontSize = 12.sp))
Text(price, style = TextStyle(color = ColorProvider(Color.White), fontSize = 20.sp))
Text("$change%", style = TextStyle(
color = ColorProvider(if (change.startsWith("-")) Color.Red else Color.Green)
))
}
}
}
}
Мінімальний інтервал оновлення через AppWidgetManager — 30 хвилин (обмеження Android). Для частіших оновлень потрібен WorkManager з PeriodicWorkRequest, але на Android 12+ фонові задачі регулюються Battery Optimizer — у Doze mode інтервали розтягуються.
Що входить у роботу
- iOS: WidgetKit extension,
TimelineProvider, SwiftUI-вёрстка, App Groups для shared data - Android: Jetpack Glance widget, WorkManager для оновлень
- Інтеграція з API курсів (CoinGecko, Binance, CoinMarketCap або власний бекенд)
- Підтримка кількох розмірів віджета
- Deep link із віджета в потрібний екран додатку
- Тестування поведінки при відсутності мережі та застарілих даних
Графік
3–5 днів на кожну платформу. Якщо потрібні обидві — 5–8 днів суммарно з урахуванням спільної логіки отримання даних. Вартість розраховується індивідуально.







