ThreeTenABP — Android üçün adapter kitabxanası, Android 8-dən aşağı (API < 26) cihazlarda java.time API-ni (org.threeten.bp paketi) təmin edir. Spesifikasiyaya görə Jake Wharton (GitHub, 2023), kitabxana ThreeTen-Backport layihəsi üzərində örtük olub, resurs optimallaşdırması və AssetManager vasitəsilə tzdata dəstəyi nəzərə alınmaqla Android üçün uyğunlaşdırılıb.
Əsas məqamlar
ThreeTenABP (ThreeTen Android Backport) — Jake Wharton tərəfindən köhnə Android versiyalarında Java 8 tarix/vaxt API-dən istifadə üçün yaradılmış kitabxanadır. ThreeTen-Backport layihəsi üçün adapter olub, java.time (JSR-310) Java 7 və Android API < 26-ya port edir.
Kitabxananın həll etdiyi əsas problem: Android 8-dən (API 26) əvvəlki versiyalar java.time-ı standart tərkibə daxil etmirdi. Tərtibatçılar java.util.Date/Calendar istifadə etməyə və ya Joda-Time qoşmağa məcbur idilər. ThreeTenABP daxili java.time ilə eyni müasir API-ni təmin edir, lakin org.threeten.bp paketi vasitəsilə.
Məlumatlara görə GitHub deposu (2023), kitabxana Android üçün optimallaşdırılıb: tzdata məlumatları (IANA Time Zone Database) assets-də saxlanılır və AssetManager vasitəsilə yüklənir, masaüstü versiyadakı kimi classpath vasitəsilə deyil. Bu APK ölçüsünü azaldır və yükləməni sürətləndirir.
Son sabit versiya — 1.4.0 (avqust 2021). Kitabxana dəstək rejimindədir, çünki desugaring-in geniş yayılması ilə ona ehtiyaz azalır, lakin minimal API < 26 olan layihələr üçün aktual qalır.
Java 8-də (2014) java.time peyda olmamışdan əvvəl tərtibatçılar java.util.Date və java.util.Calendar istifadə edirdilər. Bu siniflərin ciddi çatışmazlıqları var: Date mutable-dır, Calendar intuitiv olmayan sabitlərdən istifadə edir (Calendar.JANUARY = 0), hər iki sinif thread-safe deyil və saat qurşaqları ilə işləyərkən səhvlərə meyllidir.
Joda-Time Java 8-dən əvvəl de-fakto standart idi, lakin onun yaradıcısı Stephen Colebourne java.time-ı rəsmi əvəzedici kimi dizayn etdi, Joda-Time təcrübəsinə əsaslanaraq və onun çatışmazlıqlarını nəzərə alaraq. java.time paketi JDK 8-ə daxil oldu, lakin Android onu API 26-ya qədər almadı.
ThreeTen-Backport — eyni müəllif (Stephen Colebourne) tərəfindən yaradılmış java.time-ın Java 7-yə portudur. Bütün əsas sinifləri əhatə edir: LocalDate, LocalTime, LocalDateTime, ZonedDateTime, Instant, Duration, Period, DateTimeFormatter. ThreeTenABP bu portu Android üçün uyğunlaşdırır, AssetsManager vasitəsilə işə salma və mobil cihazlar üçün optimallaşdırma əlavə edir.
Beləliklə, ThreeTenABP Android 4.0+ (API 14+) cihazlarda müasir tarix/vaxt API-dən istifadə etməyə imkan verir, ƏS yeniləməsini gözləmədən.
Qoşulma iki addımda həyata keçirilir: build.gradle (app-level) faylına asılılıq əlavə etmək və Application sinfində işə salma. Vacib: ThreeTenABP compileSdk 21-dən aşağı olmayan və Gradle versiyası 4.0-dan aşağı olmayan tələb edir.
Asılılıq dependencies bölməsinə əlavə olunur: implementation “com.jakewharton.threetenabp:threetenabp:1.4.0”. 1.4.0 buraxılışından bəri kitabxana yenilənməyib, çünki sabitdir və bütün lazımi halları əhatə edir.
Rəsmi sənədlərə görə ofisial dokumentasiya, kitabxana tzdata-nı assets-də ehtiva edir. Əgər tətbiqdə artıq digər faylları olan assets qovluğu varsa, ThreeTenABP onlarla düzgün şəkildə birgə mövcud olur. Tzdata ölçüsü sıxılmış halda təxminən 200 KB-dır.
// build.gradle (tətbiq səviyyəsi)
android {
compileOptions {
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
}
}
dependencies {
implementation "com.jakewharton.threetenabp:threetenabp:1.4.0"
}
org.threeten.bp-dən hər hansı sinifdən istifadə etməzdən əvvəl kitabxananı işə salmaq lazımdır. İşə salma bir dəfə Application.onCreate() daxilində AndroidThreeTen.init(this) çağırışı vasitəsilə həyata keçirilir.
İşə salma tzdata məlumatlarını assets-dən yükləyir və sistem saatını konfiqurasiya edir. init() çağırışı olmadan now() metodları kitabxananın işə salınmadığı barədə IllegalStateException istisnası qaytaracaq.
Testlər üçün AndroidThreeTen.init(applicationContext, zoneId) — saat qurşağının açıq göstərilməsi ilə overload istifadə oluna bilər. Bu testlərin proqnozlaşdırıla bilən davranışı üçün faydalıdır. Yalnız tzdata olmadan əsas işə salma lazımdırsa — AndroidThreeTen.initWithoutFiles(context) istifadə edin.
class App : Application() {
override fun onCreate() {
super.onCreate()
AndroidThreeTen.init(this)
}
}
// İşə salmadan sonra istifadə
val today = LocalDate.now()
val now = LocalDateTime.now()
ThreeTenABP java.time-ın bütün əsas siniflərini təmin edir, lakin org.threeten.bp paketində. API orijinal java.time ilə praktiki olaraq eynidir, bu da API 26+-ya keçərkən miqrasiyanı asanlaşdırır.
Əsas siniflər:
Köməkçi siniflər də dəstəklənir: Clock, DayOfWeek, Month, Year, YearMonth, MonthDay. Saat qurşaqları kitabxana ilə birlikdə verilir (IANA tzdata). ThreeTenABP 1.4.0-da tzdata versiyası 2021a-ya uyğundur.
Android Gradle Plugin 4.0 (2020) və desugar_jdk_libs-dən başlayaraq, tərtibatçılar coreLibraryDesugaring vasitəsilə bütün Android versiyalarında java.time istifadə etmək imkanı əldə etdilər. Desugaring bayt kodunu elə transformasiya edir ki, java.time çağırışları əlavə kitabxanalar olmadan köhnə API-lərdə işləyir.
Desugaring-in üstünlükləri: orijinal java.time paketi istifadə olunur (org.threeten.bp yox), işə salma tələb olunmur, Android Studio ilə tam inteqrasiya. Çatışmazlıqları: AGP 4.0+ tələb edir, qurma vaxtını artırır, APK ölçüsü 2-3 MB arta bilər.
ThreeTenABP AGP-ni 4.0+-a yeniləyə bilməyən legacy layihələr və ya APK ölçüsünün kritik olduğu hallar üçün ən yaxşı seçim olaraq qalır. Həmçinin ThreeTenABP quraşdırmada daha sadədir — bir asılılıq və bir sətir işə salma kifayətdir. Stack Overflow (2024) məlumatlarına görə, minSdk < 26 olan layihələrin təxminən 30%-i hələ də desugaring əvəzinə ThreeTenABP istifadə edir.
Birinci nümunə — ThreeTenABP vasitəsilə tarixlərlə iş. API java.time ilə eynidir, lakin importlar org.threeten.bp-dən gəlir. Bu, miqrasiyadan sonra yalnız importların dəyişdirilməsini tələb edən kod yazmağa imkan verir.
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 nümunə — tarixin formatlaşdırılması. org.threeten.bp-dən DateTimeFormatter java.time-dakı kimi işləyir.
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ü nümunə — ZonedDateTime ilə iş və ThreeTenABP-də saat qurşaqları arasında konvertasiya.
import org.threeten.bp.ZonedDateTime
import org.threeten.bp.ZoneId
fun convertTimeZone(
time: ZonedDateTime,
targetZone: ZoneId
): ZonedDateTime {
return time.withZoneSameInstant(targetZone)
}
minSdk 26-ya qaldırıldıqda ThreeTenABP-dən imtina edib daxili java.time-a keçmək olar. Miqrasiya prosesi bir neçə addımı əhatə edir və diqqətli test tələb edir.
Birinci addım — importların dəyişdirilməsi. org.threeten.bp importları java.time ilə əvəz olunur. Əksər hallarda sinif adları uyğundur: LocalDate → java.time.LocalDate, ZonedDateTime → java.time.ZonedDateTime. İstisna DateTimeFormatter-dir — ThreeTenABP-də org.threeten.bp.format, java.time-da isə java.time.format.
İkinci addım — işə salmanın silinməsi. AndroidThreeTen.init(this) sətri artıq lazım deyil, çünki java.time Android SDK-ya daxildir. Application.onCreate() çağırışını və build.gradle-dən asılılığı silin.
Üçüncü addım — minSdk 26-dan aşağı qalırsa, asılılığı desugaring ilə əvəz edin. compileOptions-da isCoreLibraryDesugaringEnabled = true və desugar_jdk_libs asılılığını əlavə edin. Bu, ThreeTenABP olmadan köhnə API-lərdə java.time işini təmin edəcək. Google I/O (2023) məlumatlarına görə, desugaring yeni layihələr üçün üstünlük verilən üsuldur.
// build.gradle — ThreeTenABP-ni desugaring ilə əvəz et
android {
compileOptions {
isCoreLibraryDesugaringEnabled = true
}
}
dependencies {
// Sil: implementation “com.jakewharton.threetenabp:threetenabp:1.4.0”
// Əlavə et:
"coreLibraryDesugaring"("com.android.tools:desugar_jdk_libs:2.1.4")
}
// Application-dən AndroidThreeTen.init(this) sil
Tez-tez verilən suallar
Texniki olaraq — bəli, lakin bunun mənası yoxdur. Desugaring istifadə olunursa, daxili java.time artıq mövcuddur. Hər iki kitabxananın istifadəsi kodun təkrarlanmasına və APK ölçüsünün artmasına səbəb olacaq. Layihə üçün bir yanaşma seçin.
İşə salma IANA Time Zone Database məlumatlarını assets-dən yaddaşa yükləyir. Standart JDK-da tzdata classpath vasitəsilə mövcuddur, lakin Android AssetManager istifadə edir. init() metodu məlumatları sistem qovluğuna kopyalayaraq onları ZoneId üçün əlçatan edir.
ThreeTenABP API 14+ (Android 4.0 Ice Cream Sandwich və daha yuxarı) dəstəkləyir. İstifadə üçün Java 8 compatibility (compileOptions-da sourceCompatibility və targetCompatibility) tələb olunur. API 26+-da kitabxana lazım deyil — daxili java.time istifadə edin.
Saat qurşaqları kitabxana ilə birlikdə verilir. 1.4.0 versiyası tzdata 2021a daxildir. Yeniləmək üçün ThreeTenABP versiyasını yeniləmək və ya assets-də tzdata-nı əl ilə əvəz etmək lazımdır. Tzdata-nın son versiyalarını IANA deposundan və ya ThreeTen-Backport vasitəsilə əldə etmək olar.
Vahid testlər üçün zonanın açıq göstərilməsi ilə AndroidThreeTen.init(context, zoneId) istifadə edin. Robolectric testləri üçün — AndroidThreeTen.init(ApplicationProvider.getApplicationContext()). Android olmadan təmiz JVM testləri üçün — ThreeTenABP olmadan birbaşa ThreeTen-Backport istifadə edin.
Nəticə
Açar təslim mobil tətbiq hazırlayacağıq
IT Sectr 2017-ci ildən startaplar və bizneslər üçün iOS və Android tətbiqləri yaradır. Sizə məsləhət verəcəyik və ən yaxşı həlli təklif edəcəyik.
Həm də oxuyun