From d21c1472038ab8cba072b1d1085a15f6c11e424e Mon Sep 17 00:00:00 2001 From: arkon Date: Sun, 1 Nov 2020 15:12:16 -0500 Subject: [PATCH] Singleton instance of Json serializer --- app/src/main/java/eu/kanade/tachiyomi/AppModule.kt | 3 +++ .../data/download/DownloadPendingDeleter.kt | 9 ++++++--- .../kanade/tachiyomi/data/download/DownloadStore.kt | 5 +++-- .../kanade/tachiyomi/data/track/anilist/Anilist.kt | 7 +++++-- .../tachiyomi/data/track/anilist/AnilistApi.kt | 11 +++++++---- .../kanade/tachiyomi/data/track/bangumi/Bangumi.kt | 7 +++++-- .../tachiyomi/data/track/bangumi/BangumiApi.kt | 11 +++++++---- .../data/track/bangumi/BangumiInterceptor.kt | 5 ++++- .../tachiyomi/data/track/shikimori/Shikimori.kt | 7 +++++-- .../tachiyomi/data/track/shikimori/ShikimoriApi.kt | 13 ++++++++----- .../data/track/shikimori/ShikimoriInterceptor.kt | 5 ++++- 11 files changed, 57 insertions(+), 26 deletions(-) diff --git a/app/src/main/java/eu/kanade/tachiyomi/AppModule.kt b/app/src/main/java/eu/kanade/tachiyomi/AppModule.kt index 9b480ec931..d8dae349e1 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/AppModule.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/AppModule.kt @@ -13,6 +13,7 @@ import eu.kanade.tachiyomi.network.NetworkHelper import eu.kanade.tachiyomi.source.SourceManager import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.launch +import kotlinx.serialization.json.Json import uy.kohesive.injekt.api.InjektModule import uy.kohesive.injekt.api.InjektRegistrar import uy.kohesive.injekt.api.addSingleton @@ -44,6 +45,8 @@ class AppModule(val app: Application) : InjektModule { addSingletonFactory { Gson() } + addSingletonFactory { Json { ignoreUnknownKeys = true } } + // Asynchronously init expensive components for a faster cold start GlobalScope.launch { get() } diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/download/DownloadPendingDeleter.kt b/app/src/main/java/eu/kanade/tachiyomi/data/download/DownloadPendingDeleter.kt index 1da4813c88..f9ff46b5f2 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/download/DownloadPendingDeleter.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/download/DownloadPendingDeleter.kt @@ -8,6 +8,7 @@ import kotlinx.serialization.Serializable import kotlinx.serialization.decodeFromString import kotlinx.serialization.encodeToString import kotlinx.serialization.json.Json +import uy.kohesive.injekt.injectLazy /** * Class used to keep a list of chapters for future deletion. @@ -16,6 +17,8 @@ import kotlinx.serialization.json.Json */ class DownloadPendingDeleter(context: Context) { + private val json: Json by injectLazy() + /** * Preferences used to store the list of chapters to delete. */ @@ -49,7 +52,7 @@ class DownloadPendingDeleter(context: Context) { val existingEntry = preferences.getString(manga.id!!.toString(), null) if (existingEntry != null) { // Existing entry found on preferences, decode json and add the new chapter - val savedEntry = Json.decodeFromString(existingEntry) + val savedEntry = json.decodeFromString(existingEntry) // Append new chapters val newChapters = savedEntry.chapters.addUniqueById(chapters) @@ -65,7 +68,7 @@ class DownloadPendingDeleter(context: Context) { } // Save current state - val json = Json.encodeToString(newEntry) + val json = json.encodeToString(newEntry) preferences.edit { putString(newEntry.manga.id.toString(), json) } @@ -97,7 +100,7 @@ class DownloadPendingDeleter(context: Context) { private fun decodeAll(): List { return preferences.all.values.mapNotNull { rawEntry -> try { - (rawEntry as? String)?.let { Json.decodeFromString(it) } + (rawEntry as? String)?.let { json.decodeFromString(it) } } catch (e: Exception) { null } diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/download/DownloadStore.kt b/app/src/main/java/eu/kanade/tachiyomi/data/download/DownloadStore.kt index d885fb6f1b..22b13d676a 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/download/DownloadStore.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/download/DownloadStore.kt @@ -28,6 +28,7 @@ class DownloadStore( */ private val preferences = context.getSharedPreferences("active_downloads", Context.MODE_PRIVATE) + private val json: Json by injectLazy() private val db: DatabaseHelper by injectLazy() /** @@ -109,7 +110,7 @@ class DownloadStore( */ private fun serialize(download: Download): String { val obj = DownloadObject(download.manga.id!!, download.chapter.id!!, counter++) - return Json.encodeToString(obj) + return json.encodeToString(obj) } /** @@ -119,7 +120,7 @@ class DownloadStore( */ private fun deserialize(string: String): DownloadObject? { return try { - Json.decodeFromString(string) + json.decodeFromString(string) } catch (e: Exception) { null } diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/track/anilist/Anilist.kt b/app/src/main/java/eu/kanade/tachiyomi/data/track/anilist/Anilist.kt index cf4c1ef94b..7725a2ded4 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/track/anilist/Anilist.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/track/anilist/Anilist.kt @@ -11,6 +11,7 @@ import kotlinx.serialization.encodeToString import kotlinx.serialization.json.Json import rx.Completable import rx.Observable +import uy.kohesive.injekt.injectLazy class Anilist(private val context: Context, id: Int) : TrackService(id) { @@ -34,6 +35,8 @@ class Anilist(private val context: Context, id: Int) : TrackService(id) { override val name = "AniList" + private val json: Json by injectLazy() + private val interceptor by lazy { AnilistInterceptor(this, getPassword()) } private val api by lazy { AnilistApi(client, interceptor) } @@ -196,12 +199,12 @@ class Anilist(private val context: Context, id: Int) : TrackService(id) { } fun saveOAuth(oAuth: OAuth?) { - preferences.trackToken(this).set(Json.encodeToString(oAuth)) + preferences.trackToken(this).set(json.encodeToString(oAuth)) } fun loadOAuth(): OAuth? { return try { - Json.decodeFromString(preferences.trackToken(this).get()) + json.decodeFromString(preferences.trackToken(this).get()) } catch (e: Exception) { null } diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/track/anilist/AnilistApi.kt b/app/src/main/java/eu/kanade/tachiyomi/data/track/anilist/AnilistApi.kt index d7e97c64d7..2de55d3413 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/track/anilist/AnilistApi.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/track/anilist/AnilistApi.kt @@ -23,10 +23,13 @@ import okhttp3.OkHttpClient import okhttp3.Request import okhttp3.RequestBody.Companion.toRequestBody import rx.Observable +import uy.kohesive.injekt.injectLazy import java.util.Calendar class AnilistApi(val client: OkHttpClient, interceptor: AnilistInterceptor) { + private val json: Json by injectLazy() + private val jsonMime = "application/json; charset=utf-8".toMediaTypeOrNull() private val authClient = client.newBuilder().addInterceptor(interceptor).build() @@ -61,7 +64,7 @@ class AnilistApi(val client: OkHttpClient, interceptor: AnilistInterceptor) { if (responseBody.isEmpty()) { throw Exception("Null Response") } - val response = Json.decodeFromString(responseBody) + val response = json.decodeFromString(responseBody) track.library_id = response["data"]!!.jsonObject["SaveMediaListEntry"]!!.jsonObject["id"]!!.jsonPrimitive.long track } @@ -143,7 +146,7 @@ class AnilistApi(val client: OkHttpClient, interceptor: AnilistInterceptor) { if (responseBody.isEmpty()) { throw Exception("Null Response") } - val response = Json.decodeFromString(responseBody) + val response = json.decodeFromString(responseBody) val data = response["data"]!!.jsonObject val page = data["Page"]!!.jsonObject val media = page["media"]!!.jsonArray @@ -203,7 +206,7 @@ class AnilistApi(val client: OkHttpClient, interceptor: AnilistInterceptor) { if (responseBody.isEmpty()) { throw Exception("Null Response") } - val response = Json.decodeFromString(responseBody) + val response = json.decodeFromString(responseBody) val data = response["data"]!!.jsonObject val page = data["Page"]!!.jsonObject val media = page["mediaList"]!!.jsonArray @@ -248,7 +251,7 @@ class AnilistApi(val client: OkHttpClient, interceptor: AnilistInterceptor) { if (responseBody.isEmpty()) { throw Exception("Null Response") } - val response = Json.decodeFromString(responseBody) + val response = json.decodeFromString(responseBody) val data = response["data"]!!.jsonObject val viewer = data["Viewer"]!!.jsonObject Pair(viewer["id"]!!.jsonPrimitive.int, viewer["mediaListOptions"]!!.jsonObject["scoreFormat"]!!.jsonPrimitive.content) diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/track/bangumi/Bangumi.kt b/app/src/main/java/eu/kanade/tachiyomi/data/track/bangumi/Bangumi.kt index a2a8a6c7fc..ae8aad8ada 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/track/bangumi/Bangumi.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/track/bangumi/Bangumi.kt @@ -11,11 +11,14 @@ import kotlinx.serialization.encodeToString import kotlinx.serialization.json.Json import rx.Completable import rx.Observable +import uy.kohesive.injekt.injectLazy class Bangumi(private val context: Context, id: Int) : TrackService(id) { override val name = "Bangumi" + private val json: Json by injectLazy() + private val interceptor by lazy { BangumiInterceptor(this) } private val api by lazy { BangumiApi(client, interceptor) } @@ -111,12 +114,12 @@ class Bangumi(private val context: Context, id: Int) : TrackService(id) { } fun saveToken(oauth: OAuth?) { - preferences.trackToken(this).set(Json.encodeToString(oauth)) + preferences.trackToken(this).set(json.encodeToString(oauth)) } fun restoreToken(): OAuth? { return try { - Json.decodeFromString(preferences.trackToken(this).get()) + json.decodeFromString(preferences.trackToken(this).get()) } catch (e: Exception) { null } diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/track/bangumi/BangumiApi.kt b/app/src/main/java/eu/kanade/tachiyomi/data/track/bangumi/BangumiApi.kt index 6b28a5468d..ac20033204 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/track/bangumi/BangumiApi.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/track/bangumi/BangumiApi.kt @@ -20,10 +20,13 @@ import okhttp3.FormBody import okhttp3.OkHttpClient import okhttp3.Request import rx.Observable +import uy.kohesive.injekt.injectLazy import java.net.URLEncoder class BangumiApi(private val client: OkHttpClient, interceptor: BangumiInterceptor) { + private val json: Json by injectLazy() + private val authClient = client.newBuilder().addInterceptor(interceptor).build() fun addLibManga(track: Track): Observable { @@ -93,7 +96,7 @@ class BangumiApi(private val client: OkHttpClient, interceptor: BangumiIntercept if (responseBody.contains("\"code\":404")) { responseBody = "{\"results\":0,\"list\":[]}" } - val response = Json.decodeFromString(responseBody)["list"]?.jsonArray + val response = json.decodeFromString(responseBody)["list"]?.jsonArray response?.filter { it.jsonObject["type"]?.jsonPrimitive?.int == 1 }?.map { jsonToSearch(it.jsonObject) } } } @@ -134,7 +137,7 @@ class BangumiApi(private val client: OkHttpClient, interceptor: BangumiIntercept .map { netResponse -> // get comic info val responseBody = netResponse.body?.string().orEmpty() - jsonToTrack(Json.decodeFromString(responseBody)) + jsonToTrack(json.decodeFromString(responseBody)) } } @@ -151,7 +154,7 @@ class BangumiApi(private val client: OkHttpClient, interceptor: BangumiIntercept .asObservableSuccess() .map { netResponse -> val resp = netResponse.body?.string() - val coll = Json { ignoreUnknownKeys = true }.decodeFromString(resp!!) + val coll = json.decodeFromString(resp!!) track.status = coll.status?.id!! track.last_chapter_read = coll.ep_status!! track @@ -164,7 +167,7 @@ class BangumiApi(private val client: OkHttpClient, interceptor: BangumiIntercept if (responseBody.isEmpty()) { throw Exception("Null Response") } - Json { ignoreUnknownKeys = true }.decodeFromString(responseBody) + json.decodeFromString(responseBody) } } diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/track/bangumi/BangumiInterceptor.kt b/app/src/main/java/eu/kanade/tachiyomi/data/track/bangumi/BangumiInterceptor.kt index 475e7287bf..033a167dc0 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/track/bangumi/BangumiInterceptor.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/track/bangumi/BangumiInterceptor.kt @@ -5,9 +5,12 @@ import kotlinx.serialization.json.Json import okhttp3.FormBody import okhttp3.Interceptor import okhttp3.Response +import uy.kohesive.injekt.injectLazy class BangumiInterceptor(val bangumi: Bangumi) : Interceptor { + private val json: Json by injectLazy() + /** * OAuth object used for authenticated requests. */ @@ -30,7 +33,7 @@ class BangumiInterceptor(val bangumi: Bangumi) : Interceptor { if (currAuth.isExpired()) { val response = chain.proceed(BangumiApi.refreshTokenRequest(currAuth.refresh_token!!)) if (response.isSuccessful) { - newAuth(Json { ignoreUnknownKeys = true }.decodeFromString(response.body!!.string())) + newAuth(json.decodeFromString(response.body!!.string())) } else { response.close() } diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/track/shikimori/Shikimori.kt b/app/src/main/java/eu/kanade/tachiyomi/data/track/shikimori/Shikimori.kt index d0244e7c00..113f1a90c6 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/track/shikimori/Shikimori.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/track/shikimori/Shikimori.kt @@ -11,6 +11,7 @@ import kotlinx.serialization.encodeToString import kotlinx.serialization.json.Json import rx.Completable import rx.Observable +import uy.kohesive.injekt.injectLazy class Shikimori(private val context: Context, id: Int) : TrackService(id) { @@ -28,6 +29,8 @@ class Shikimori(private val context: Context, id: Int) : TrackService(id) { override val name = "Shikimori" + private val json: Json by injectLazy() + private val interceptor by lazy { ShikimoriInterceptor(this) } private val api by lazy { ShikimoriApi(client, interceptor) } @@ -116,12 +119,12 @@ class Shikimori(private val context: Context, id: Int) : TrackService(id) { } fun saveToken(oauth: OAuth?) { - preferences.trackToken(this).set(Json.encodeToString(oauth)) + preferences.trackToken(this).set(json.encodeToString(oauth)) } fun restoreToken(): OAuth? { return try { - Json.decodeFromString(preferences.trackToken(this).get()) + json.decodeFromString(preferences.trackToken(this).get()) } catch (e: Exception) { null } diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/track/shikimori/ShikimoriApi.kt b/app/src/main/java/eu/kanade/tachiyomi/data/track/shikimori/ShikimoriApi.kt index ed9e834398..54a85019fa 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/track/shikimori/ShikimoriApi.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/track/shikimori/ShikimoriApi.kt @@ -24,9 +24,12 @@ import okhttp3.OkHttpClient import okhttp3.Request import okhttp3.RequestBody.Companion.toRequestBody import rx.Observable +import uy.kohesive.injekt.injectLazy class ShikimoriApi(private val client: OkHttpClient, interceptor: ShikimoriInterceptor) { + private val json: Json by injectLazy() + private val jsonime = "application/json; charset=utf-8".toMediaTypeOrNull() private val authClient = client.newBuilder().addInterceptor(interceptor).build() @@ -72,7 +75,7 @@ class ShikimoriApi(private val client: OkHttpClient, interceptor: ShikimoriInter if (responseBody.isEmpty()) { throw Exception("Null Response") } - val response = Json.decodeFromString(responseBody) + val response = json.decodeFromString(responseBody) response.map { jsonToSearch(it.jsonObject) } } } @@ -125,7 +128,7 @@ class ShikimoriApi(private val client: OkHttpClient, interceptor: ShikimoriInter .asObservableSuccess() .map { netResponse -> val responseBody = netResponse.body?.string().orEmpty() - Json.decodeFromString(responseBody) + json.decodeFromString(responseBody) }.flatMap { mangas -> authClient.newCall(request) .asObservableSuccess() @@ -134,7 +137,7 @@ class ShikimoriApi(private val client: OkHttpClient, interceptor: ShikimoriInter if (responseBody.isEmpty()) { throw Exception("Null Response") } - val response = Json.decodeFromString(responseBody) + val response = json.decodeFromString(responseBody) if (response.size > 1) { throw Exception("Too much mangas in response") } @@ -148,7 +151,7 @@ class ShikimoriApi(private val client: OkHttpClient, interceptor: ShikimoriInter fun getCurrentUser(): Int { val user = authClient.newCall(GET("$apiUrl/users/whoami")).execute().body?.string()!! - return Json.decodeFromString(user)["id"]!!.jsonPrimitive.int + return json.decodeFromString(user)["id"]!!.jsonPrimitive.int } fun accessToken(code: String): Observable { @@ -157,7 +160,7 @@ class ShikimoriApi(private val client: OkHttpClient, interceptor: ShikimoriInter if (responseBody.isEmpty()) { throw Exception("Null Response") } - Json { ignoreUnknownKeys = true }.decodeFromString(responseBody) + json.decodeFromString(responseBody) } } diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/track/shikimori/ShikimoriInterceptor.kt b/app/src/main/java/eu/kanade/tachiyomi/data/track/shikimori/ShikimoriInterceptor.kt index d045d1a461..ba9074af8b 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/track/shikimori/ShikimoriInterceptor.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/track/shikimori/ShikimoriInterceptor.kt @@ -4,9 +4,12 @@ import kotlinx.serialization.decodeFromString import kotlinx.serialization.json.Json import okhttp3.Interceptor import okhttp3.Response +import uy.kohesive.injekt.injectLazy class ShikimoriInterceptor(val shikimori: Shikimori) : Interceptor { + private val json: Json by injectLazy() + /** * OAuth object used for authenticated requests. */ @@ -23,7 +26,7 @@ class ShikimoriInterceptor(val shikimori: Shikimori) : Interceptor { if (currAuth.isExpired()) { val response = chain.proceed(ShikimoriApi.refreshTokenRequest(refreshToken)) if (response.isSuccessful) { - newAuth(Json.decodeFromString(response.body!!.string())) + newAuth(json.decodeFromString(response.body!!.string())) } else { response.close() }