ThreeTenABP, Android 8'in altındaki (API < 26) cihazlarda java.time API'sini (org.threeten.bp paketi) sağlayan bir Android bağdaştırıcı kütüphanesidir. Jake Wharton (GitHub, 2023) tarafından belirtilen özelliklere göre, kütüphane, kaynak optimizasyonu ve AssetManager aracılığıyla tzdata desteği ile Android için uyarlanmış ThreeTen-Backport projesinin bir sarmalayıcısıdır.
Önemli Noktalar
ThreeTenABP (ThreeTen Android Backport), eski Android sürümlerinde Java 8 tarih/saat API'sini kullanmak için Jake Wharton tarafından oluşturulmuş bir kütüphanedir. ThreeTen-Backport projesi için bir bağdaştırıcıdır ve java.time'ı (JSR-310) Java 7 ve Android API < 26'ya taşır.
Kütüphanenin çözdüğü temel sorun: Android sürüm 8'den (API 26) önce java.time standart dağıtıma dahil edilmemişti. Geliştiriciler java.util.Date/Calendar kullanmaya veya Joda-Time eklemeye zorlanmıştı. ThreeTenABP, yerleşik java.time ile aynı modern API'yi sağlar, ancak org.threeten.bp paketi aracılığıyla.
GitHub deposuna (2023) göre, kütüphane Android için optimize edilmiştir: tzdata (IANA Time Zone Database) assets'te saklanır ve masaüstünde olduğu gibi classpath yerine AssetManager aracılığıyla yüklenir. Bu, APK boyutunu azaltır ve yüklemeyi hızlandırır.
En son kararlı sürüm 1.4.0'dır (Ağustos 2021). Kütüphane bakım modundadır, çünkü desugaring'in yaygın benimsenmesiyle ihtiyaç azalmaktadır, ancak minimum API < 26 olan projeler için hala geçerlidir.
Java 8'de (2014) java.time tanıtılmadan önce, geliştiriciler java.util.Date ve java.util.Calendar kullanıyordu. Bu sınıfların ciddi dezavantajları vardır: Date değiştirilebilir, Calendar sezgisel olmayan sabitler kullanır (Calendar.JANUARY = 0), her iki sınıf da iş parçacığı güvenli değildir ve saat dilimleriyle çalışırken hatalara eğilimlidir.
Joda-Time, Java 8'den önce fiili standarttı, ancak yaratıcısı Stephen Colebourne, Joda-Time deneyimine dayanarak ve eksikliklerini gidererek java.time'ı resmi yedek olarak tasarladı. java.time paketi JDK 8'e dahil edildi, ancak Android bunu API 26'ya kadar almadı.
ThreeTen-Backport, aynı yazar (Stephen Colebourne) tarafından oluşturulmuş java.time'ın Java 7'ye bir taşımasıdır. Tüm ana sınıfları içerir: LocalDate, LocalTime, LocalDateTime, ZonedDateTime, Instant, Duration, Period, DateTimeFormatter. ThreeTenABP bu taşımayı Android için uyarlar, AssetsManager aracılığıyla başlatma ve mobil cihazlar için optimizasyon ekler.
Böylece ThreeTenABP, bir işletim sistemi güncellemesi beklemeden Android 4.0+ (API 14+) cihazlarda modern tarih/saat API'sini kullanmanıza olanak tanır.
Ekleme iki adımda yapılır: build.gradle (uygulama düzeyi) bağımlılığı ekleme ve Application sınıfında başlatma. Önemli: ThreeTenABP, en az 21 compileSdk ve en az 4.0 Gradle sürümü gerektirir.
Bağımlılık, dependencies bölümüne eklenir: implementation "com.jakewharton.threetenabp:threetenabp:1.4.0". 1.4.0 sürümünün yayınlanmasından bu yana, kütüphane güncellenmemiştir, çünkü stabildir ve tüm gerekli durumları kapsar.
Resmi dokümantasyona göre, kütüphane assets içinde tzdata içerir. Uygulamada zaten başka dosyaları olan bir assets klasörü varsa, ThreeTenABP onlarla doğru şekilde bir arada bulunur. tzdata'nın boyutu sıkıştırılmış halde yaklaşık 200 KB'dir.
// build.gradle (uygulama düzeyi)
android {
compileOptions {
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
}
}
dependencies {
implementation "com.jakewharton.threetenabp:threetenabp:1.4.0"
}
org.threeten.bp'den herhangi bir sınıfı kullanmadan önce, kütüphanenin başlatılması gerekir. Başlatma, Application.onCreate() içinde AndroidThreeTen.init(this) çağrılarak bir kez gerçekleştirilir.
Başlatma, assets'ten tzdata verilerini yükler ve sistem saatini yapılandırır. init() çağrılmazsa, now() yöntemleri, kütüphanenin başlatılmadığına dair bir mesajla IllegalStateException fırlatır.
Testler için, açık saat dilimi belirtimiyle AndroidThreeTen.init(applicationContext, zoneId) kullanabilirsiniz — bu, testlerde öngörülebilir davranış için kullanışlıdır. Yalnızca tzdata olmadan temel başlatma gerekiyorsa, AndroidThreeTen.initWithoutFiles(context) kullanın.
class App : Application() {
override fun onCreate() {
super.onCreate()
AndroidThreeTen.init(this)
}
}
// Başlatma sonrası kullanım
val today = LocalDate.now()
val now = LocalDateTime.now()
ThreeTenABP, java.time'ın tüm ana sınıflarını org.threeten.bp paketinde sağlar. API, orijinal java.time ile neredeyse aynıdır ve API 26+'ya geçişi kolaylaştırır.
Ana sınıflar:
Yardımcı sınıflar da desteklenir: Clock, DayOfWeek, Month, Year, YearMonth, MonthDay. Saat dilimleri kütüphaneyle birlikte verilir (IANA tzdata). ThreeTenABP 1.4.0'daki tzdata sürümü 2021a'ya karşılık gelir.
Android Gradle Plugin 4.0 (2020) ve desugar_jdk_libs'den başlayarak, geliştiriciler coreLibraryDesugaring aracılığıyla tüm Android sürümlerinde java.time kullanma yeteneği kazandı. Desugaring, bytecode'u dönüştürerek java.time çağrılarının ek kütüphane olmadan eski API'lerde çalışmasını sağlar.
Desugaring'in avantajları: orijinal java.time paketini kullanır (org.threeten.bp değil), başlatma gerektirmez, Android Studio ile tam entegrasyon. Dezavantajları: AGP 4.0+ gerektirir, derleme süresini artırır, APK boyutu 2-3 MB artabilir.
ThreeTenABP, AGP'yi 4.0+'a güncelleyemeyen eski projeler veya APK boyutunun kritik olduğu durumlar için en iyi seçim olmaya devam ediyor. ThreeTenABP ayrıca kurulumu da daha kolaydır — sadece bir bağımlılık ve bir satır başlatma. Stack Overflow (2024)'e göre, minSdk < 26 olan projelerin yaklaşık %30'u hala desugaring yerine ThreeTenABP kullanmaktadır.
İlk örnek, ThreeTenABP kullanarak tarihlerle çalışmayı gösterir. API java.time ile aynıdır, ancak import'lar org.threeten.bp'den gelir. Bu, geçişten sonra yalnızca import'ların değiştirilmesini gerektiren kod yazmanıza olanak tanır.
import org.threeten.bp.LocalDate
import org.threeten.bp.LocalTime
import org.threeten.bp.Duration
fun isWeekend(date: LocalDate): Boolean {
val dayOfWeek = date.getDayOfWeek()
return dayOfWeek == DayOfWeek.SATURDAY ||
dayOfWeek == DayOfWeek.SUNDAY
}
fun timeBetween(
start: LocalTime, end: LocalTime
): Duration {
return Duration.between(start, end)
}
İkinci örnek, tarih biçimlendirmeyi gösterir. org.threeten.bp'den DateTimeFormatter, java.time'daki gibi çalışır.
import org.threeten.bp.LocalDateTime
import org.threeten.bp.format.DateTimeFormatter
fun formatTimestamp(dateTime: LocalDateTime): String {
val formatter = DateTimeFormatter.ofPattern("dd.MM.yyyy HH:mm")
return dateTime.format(formatter)
}
Üçüncü örnek, ThreeTenABP'de ZonedDateTime ile çalışmayı ve saat dilimleri arasında dönüştürmeyi gösterir.
import org.threeten.bp.ZonedDateTime
import org.threeten.bp.ZoneId
fun convertTimeZone(
time: ZonedDateTime,
targetZone: ZoneId
): ZonedDateTime {
return time.withZoneSameInstant(targetZone)
}
minSdk 26'ya yükseltildiğinde, ThreeTenABP'yi kaldırabilir ve yerleşik java.time'a geçebilirsiniz. Geçiş süreci birkaç adım içerir ve kapsamlı test gerektirir.
İlk adım, import'ları değiştirmektir. org.threeten.bp'den import'lar java.time olarak değiştirilir. Çoğu durumda, sınıf adları eşleşir: LocalDate → java.time.LocalDate, ZonedDateTime → java.time.ZonedDateTime. İstisna DateTimeFormatter'dır — ThreeTenABP'de org.threeten.bp.format'ta, java.time'da ise java.time.format'tadır.
İkinci adım, başlatmayı kaldırmaktır. AndroidThreeTen.init(this) satırı artık gerekli değildir, çünkü java.time Android SDK'ya yerleşiktir. Application.onCreate()'tan çağrıyı ve build.gradle'dan bağımlılığı kaldırın.
Üçüncü adım, minSdk 26'nın altında kalırsa, bağımlılığı desugaring ile değiştirmektir. compileOptions içinde isCoreLibraryDesugaringEnabled = true ve desugar_jdk_libs bağımlılığını ekleyin. Bu, ThreeTenABP olmadan eski API'lerde java.time'ın çalışmasını sağlayacaktır. Google I/O (2023)'e göre, desugaring yeni projeler için tercih edilen yaklaşımdır.
// build.gradle — ThreeTenABP'yi desugaring ile değiştir
android {
compileOptions {
isCoreLibraryDesugaringEnabled = true
}
}
dependencies {
// Kaldır: implementation "com.jakewharton.threetenabp:threetenabp:1.4.0"
// Ekle:
"coreLibraryDesugaring"("com.android.tools:desugar_jdk_libs:2.1.4")
}
// Application'dan AndroidThreeTen.init(this)'i kaldır
Sıkça Sorulan Sorular
Teknik olarak — evet, ancak bir anlamı yoktur. Desugaring kullanılıyorsa, yerleşik java.time zaten mevcuttur. Her iki kütüphaneyi kullanmak kod tekrarına ve APK boyutunda artışa yol açar. Projeniz için bir yaklaşım seçin.
Başlatma, IANA Time Zone Database'i assets'ten belleğe yükler. Standart JDK'da tzdata classpath aracılığıyla kullanılabilir, ancak Android AssetManager kullanır. init() yöntemi, verileri sistem dizinine kopyalayarak ZoneId için kullanılabilir hale getirir.
ThreeTenABP, API 14+ (Android 4.0 Ice Cream Sandwich ve üzeri) destekler. Java 8 uyumluluğu gereklidir (compileOptions içinde sourceCompatibility ve targetCompatibility). API 26+'da kütüphane gerekli değildir — yerleşik java.time kullanın.
Saat dilimleri kütüphaneyle birlikte verilir. Sürüm 1.4.0, tzdata 2021a'yı içerir. Güncellemek için ThreeTenABP sürümünü güncellemeniz veya assets içindeki tzdata'yı manuel olarak değiştirmeniz gerekir. En son tzdata sürümleri IANA deposundan veya ThreeTen-Backport aracılığıyla alınabilir.
Birim testleri için, açık bölge belirtimiyle AndroidThreeTen.init(context, zoneId) kullanın. Robolectric testleri için — AndroidThreeTen.init(ApplicationProvider.getApplicationContext()). Android olmadan saf JVM testleri için — ThreeTenABP olmadan doğrudan ThreeTen-Backport kullanın.
Özet
Anahtar teslim bir mobil uygulama geliştireceğiz
IT Sectr, 2017'den beri girişimler ve işletmeler için iOS ve Android uygulamaları oluşturmaktadır. Size danışmanlık yapacak ve en iyi çözümü önereceğiz.
Ayrıca okuyun