ThreeTenABP — adapter könyvtár Androidhoz, amely java.time API-t (org.threeten.bp csomag) biztosít Android 8 alatti (API < 26) eszközökön. A specifikáció szerint Jake Wharton (GitHub, 2023), a könyvtár egy burkoló a ThreeTen-Backport projekt fölött, amely Androidhoz van adaptálva az erőforrás-optimalizálás és a tzdata AssetManageren keresztüli támogatásának figyelembevételével.
Főbb pontok
ThreeTenABP (ThreeTen Android Backport) — Jake Wharton által létrehozott könyvtár a Java 8 dátum/idő API használatára régebbi Android verziókon. Ez egy adapter a ThreeTen-Backport projekthez, amely a java.time-ot (JSR-310) portolja Java 7-re és Android API < 26-ra.
A fő probléma, amit a könyvtár megold: az Android 8-as verzióig (API 26) nem tartalmazta a java.time-ot a standard csomagban. A fejlesztők kényszerültek java.util.Date/Calendar használatára vagy Joda-Time hozzáadására. A ThreeTenABP ugyanazt a modern API-t nyújtja, mint a beépített java.time, de az org.threeten.bp csomagon keresztül.
A GitHub repozitórium (2023) szerint a könyvtár optimalizált Androidra: a tzdata adatok (IANA Time Zone Database) az assets mappában tárolódnak és AssetManageren keresztül töltődnek be, nem classpath-en keresztül, mint asztali gépen. Ez csökkenti az APK méretét és gyorsítja a betöltést.
Utolsó stabil verzió — 1.4.0 (2021. augusztus). A könyvtár támogatási módban van, mivel a desugaring széles körű elterjedésével csökken az iránta való igény, de továbbra is releváns a minimális API < 26 projektek számára.
A java.time megjelenése (Java 8, 2014) előtt a fejlesztők java.util.Date és java.util.Calendar osztályokat használtak. Ezek az osztályok komoly hiányosságokkal rendelkeznek: a Date módosítható, a Calendar nem intuitív konstansokat használ (Calendar.JANUARY = 0), mindkét osztály nem thread-safe és hajlamos a hibára az időzónákkal való munka során.
A Joda-Time volt a de facto standard Java 8 előtt, de alkotója, Stephen Colebourne a java.time-ot tervezte meg hivatalos helyettesítőként, a Joda-Time tapasztalataira építve és annak hiányosságait figyelembe véve. A java.time csomag részévé vált a JDK 8-nak, de az Android csak API 26-tól kapta meg.
ThreeTen-Backport — a java.time portolása Java 7-re, amelyet ugyanaz a szerző (Stephen Colebourne) készített. Tartalmazza az összes fő osztályt: LocalDate, LocalTime, LocalDateTime, ZonedDateTime, Instant, Duration, Period, DateTimeFormatter. A ThreeTenABP ezt a portot adaptálja Androidra, hozzáadva az inicializálást AssetsManageren keresztül és optimalizálást mobil eszközökhöz.
Így a ThreeTenABP lehetővé teszi a modern dátum/idő API használatát Android 4.0+ (API 14+) eszközökön anélkül, hogy meg kellene várni az operációs rendszer frissítését.
A csatlakoztatás két lépésben történik: függőség hozzáadása a build.gradle-ben (app-level) és inicializálás az Application osztályban. Fontos: A ThreeTenABP compileSdk-t legalább 21 és Gradle verziót legalább 4.0 követel meg.
A függőség a dependencies szekcióban kerül hozzáadásra: implementation „com.jakewharton.threetenabp:threetenabp:1.4.0”. Az 1.4.0 kiadás óta a könyvtár nem frissült, mert stabil és lefedi az összes szükséges esetet.
A hivatalos dokumentáció szerint a könyvtár tartalmazza a tzdata-t az assets mappában. Ha az alkalmazásnak már van assets mappája más fájlokkal, a ThreeTenABP helyesen együtt működik velük. A tzdata mérete körülbelül 200 KB tömörített formában.
// build.gradle (alkalmazás szint)
android {
compileOptions {
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
}
}
dependencies {
implementation "com.jakewharton.threetenabp:threetenabp:1.4.0"
}
Mielőtt bármely osztályt használná az org.threeten.bp-ből, inicializálni kell a könyvtárat. Az inicializálás egyszer történik az Application.onCreate()-ban az AndroidThreeTen.init(this) meghívásával.
Az inicializálás betölti a tzdata adatokat az assets-ből és beállítja a rendszerórát. Az init() meghívása nélkül a now() metódusok IllegalStateException kivételt dobnak azzal az üzenettel, hogy a könyvtár nincs inicializálva.
Tesztekhez használható az AndroidThreeTen.init(applicationContext, zoneId) — túlterhelés az időzóna explicit megadásával. Ez hasznos a tesztek kiszámítható viselkedéséhez. Ha csak alap inicializálásra van szükség tzdata nélkül — használja a AndroidThreeTen.initWithoutFiles(context) függvényt.
class App : Application() {
override fun onCreate() {
super.onCreate()
AndroidThreeTen.init(this)
}
}
// Használat inicializálás után
val today = LocalDate.now()
val now = LocalDateTime.now()
A ThreeTenABP biztosítja az összes fő java.time osztályt, de az org.threeten.bp csomagban. Az API gyakorlatilag azonos az eredeti java.time-val, ami megkönnyíti a migrációt API 26+-ra való áttéréskor.
Fő osztályok:
Az Android Gradle Plugin 4.0 (2020) és a desugar_jdk_libs megjelenésétől a fejlesztők lehetőséget kaptak a java.time használatára az Android minden verzióján a coreLibraryDesugaring segítségével. A desugaring átalakítja a bájtkódot úgy, hogy a java.time hívások működjenek a régi API-ken többletkönyvtárak nélkül.
A desugaring előnyei: az eredeti java.time csomagot használja (nem org.threeten.bp), nem igényel inicializálást, teljes integráció az Android Studio-val. Hátrányok: AGP 4.0+ szükséges, növeli a fordítási időt, az APK mérete 2-3 MB-tal nőhet.
A ThreeTenABP továbbra is a legjobb választás azon legacy projektek számára, amelyek nem tudják frissíteni az AGP-t 4.0+-ra, vagy ahol az APK mérete kritikus. A ThreeTenABP beállítása is egyszerűbb — egy függőség és egy sor inicializálás elegendő. A Stack Overflow (2024) szerint a minSdk < 26 projektek körülbelül 30%-a még mindig ThreeTenABP-t használ desugaring helyett.
Első példa — munka dátumokkal ThreeTenABP-n keresztül. Az API megegyezik a java.time-val, de az importok az org.threeten.bp-ből származnak. Ez lehetővé teszi olyan kód írását, amely migráció után csak az importok cseréjét igényli.
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)
}
Második példa — dátum formázása. Az org.threeten.bp-ből származó DateTimeFormatter ugyanúgy működik, mint a java.time-ban.
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)
}
Harmadik példa — munka ZonedDateTime-val és konverzió időzónák között ThreeTenABP-ben.
import org.threeten.bp.ZonedDateTime
import org.threeten.bp.ZoneId
fun convertTimeZone(
time: ZonedDateTime,
targetZone: ZoneId
): ZonedDateTime {
return time.withZoneSameInstant(targetZone)
}
A minSdk 26-ra emelésekor el lehet hagyni a ThreeTenABP-t áttérni a beépített java.time-ra. A migrációs folyamat több lépésből áll és alapos tesztelést igényel.
Első lépés — importok cseréje. Az org.threeten.bp importok java.time-ra változnak. A legtöbb esetben az osztálynevek megegyeznek: LocalDate → java.time.LocalDate, ZonedDateTime → java.time.ZonedDateTime. Kivétel a DateTimeFormatter — ThreeTenABP-ben org.threeten.bp.format-ban, java.time-ban java.time.format-ban van.
Második lépés — inicializálás eltávolítása. A AndroidThreeTen.init(this) sorra már nincs szükség, mert a java.time be van építve az Android SDK-ba. Távolítsa el a hívást az Application.onCreate()-ból és a függőséget a build.gradle-ből.
Harmadik lépés — a függőség cseréje desugaringre, ha a minSdk 26 alatt marad. Adja hozzá az isCoreLibraryDesugaringEnabled = true értéket a compileOptions-ban és a desugar_jdk_libs függőséget. Ez biztosítja a java.time működését régi API-ken ThreeTenABP nélkül. A Google I/O (2023) szerint a desugaring az előnyben részesített módszer új projektekhez.
// build.gradle — ThreeTenABP cseréje desugaringre
android {
compileOptions {
isCoreLibraryDesugaringEnabled = true
}
}
dependencies {
// Távolítás: implementation „com.jakewharton.threetenabp:threetenabp:1.4.0”
// Hozzáadás:
"coreLibraryDesugaring"("com.android.tools:desugar_jdk_libs:2.1.4")
}
// AndroidThreeTen.init(this) eltávolítása az Application-ből
Gyakran ismételt kérdések
Technikailag — igen, de nincs értelme. Ha desugaringet használ, a beépített java.time már elérhető. Mindkét könyvtár használata kódduplikációhoz és az APK méret növekedéséhez vezet. Válasszon egy megközelítést a projekthez.
Az inicializálás betölti az IANA Time Zone Database adatokat az assets-ből a memóriába. Standard JDK-n a tzdata classpath-en keresztül érhető el, de Android AssetManager-t használ. Az init() metódus másolja az adatokat a rendszerkönyvtárba, elérhetővé téve azokat a ZoneId számára.
A ThreeTenABP API 14+ (Android 4.0 Ice Cream Sandwich és újabb) verziókat támogat. Használathoz Java 8 compatibility szükséges (sourceCompatibility és targetCompatibility a compileOptions-ban). API 26+ esetén a könyvtár nem szükséges — használja a beépített java.time-ot.
Az időzónák a könyvtárral együtt kerülnek szállításra. Az 1.4.0 verzió a tzdata 2021a-t tartalmazza. Frissítéshez frissíteni kell a ThreeTenABP verziót vagy kézzel cserélni a tzdata-t az assets mappában. A tzdata legújabb verziói az IANA repozitóriumból vagy ThreeTen-Backporton keresztül szerezhetők be.
Unit tesztekhez használja az AndroidThreeTen.init(context, zoneId) függvényt a zóna explicit megadásával. Robolectric tesztekhez — AndroidThreeTen.init(ApplicationProvider.getApplicationContext()). Tiszta JVM tesztekhez Android nélkül — használja közvetlenül a ThreeTen-Backport-ot ThreeTenABP nélkül.
Összefoglaló
Kulcsrakész mobilalkalmazást fejlesztünk
Az IT Sectr 2017 óta készít iOS és Android alkalmazásokat induló vállalkozásoknak és vállalkozásoknak. Tanácsot adunk, és a legjobb megoldást javasoljuk.
Olvassa el is