From 9e399b69ead3c107acffc7f7693b8f9b915d11dd Mon Sep 17 00:00:00 2001 From: Yuri Schimke Date: Fri, 10 Feb 2023 20:29:43 +0000 Subject: [PATCH 1/2] Improve network pooling and avoid startup image fetches. Change-Id: If747fb0833d31ce7c9bedffd400160e979bc945e --- app/build.gradle.kts | 1 - .../apps/nowinandroid/NiaApplication.kt | 21 +++------ core/network/build.gradle.kts | 3 ++ .../core/network/di/NetworkModule.kt | 47 +++++++++++++++++++ .../network/retrofit/RetrofitNiaNetwork.kt | 16 ++----- 5 files changed, 60 insertions(+), 28 deletions(-) diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 4163090ce..960a0f48b 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -129,7 +129,6 @@ dependencies { implementation(libs.androidx.profileinstaller) implementation(libs.coil.kt) - implementation(libs.coil.kt.svg) } // androidx.test is forcing JUnit, 4.12. This forces it to use 4.13 diff --git a/app/src/main/java/com/google/samples/apps/nowinandroid/NiaApplication.kt b/app/src/main/java/com/google/samples/apps/nowinandroid/NiaApplication.kt index 62629925e..699f52575 100644 --- a/app/src/main/java/com/google/samples/apps/nowinandroid/NiaApplication.kt +++ b/app/src/main/java/com/google/samples/apps/nowinandroid/NiaApplication.kt @@ -19,33 +19,24 @@ package com.google.samples.apps.nowinandroid import android.app.Application import coil.ImageLoader import coil.ImageLoaderFactory -import coil.decode.SvgDecoder import com.google.samples.apps.nowinandroid.sync.initializers.Sync import dagger.hilt.android.HiltAndroidApp +import javax.inject.Inject +import javax.inject.Provider /** * [Application] class for NiA */ @HiltAndroidApp class NiaApplication : Application(), ImageLoaderFactory { + @Inject + lateinit var imageLoader: Provider + override fun onCreate() { super.onCreate() // Initialize Sync; the system responsible for keeping data in the app up to date. Sync.initialize(context = this) } - /** - * Since we're displaying SVGs in the app, Coil needs an ImageLoader which supports this - * format. During Coil's initialization it will call `applicationContext.newImageLoader()` to - * obtain an ImageLoader. - * - * @see Coil - */ - override fun newImageLoader(): ImageLoader { - return ImageLoader.Builder(this) - .components { - add(SvgDecoder.Factory()) - } - .build() - } + override fun newImageLoader(): ImageLoader = imageLoader.get() } diff --git a/core/network/build.gradle.kts b/core/network/build.gradle.kts index 57a75a8bf..97a68b3a5 100644 --- a/core/network/build.gradle.kts +++ b/core/network/build.gradle.kts @@ -51,4 +51,7 @@ dependencies { implementation(libs.okhttp.logging) implementation(libs.retrofit.core) implementation(libs.retrofit.kotlin.serialization) + + implementation(libs.coil.kt) + implementation(libs.coil.kt.svg) } diff --git a/core/network/src/main/java/com/google/samples/apps/nowinandroid/core/network/di/NetworkModule.kt b/core/network/src/main/java/com/google/samples/apps/nowinandroid/core/network/di/NetworkModule.kt index a272451e5..d52428f57 100644 --- a/core/network/src/main/java/com/google/samples/apps/nowinandroid/core/network/di/NetworkModule.kt +++ b/core/network/src/main/java/com/google/samples/apps/nowinandroid/core/network/di/NetworkModule.kt @@ -17,6 +17,10 @@ package com.google.samples.apps.nowinandroid.core.network.di import android.content.Context +import coil.ImageLoader +import coil.decode.SvgDecoder +import coil.util.DebugLogger +import com.google.samples.apps.nowinandroid.core.network.BuildConfig import com.google.samples.apps.nowinandroid.core.network.fake.FakeAssetManager import dagger.Module import dagger.Provides @@ -24,6 +28,9 @@ import dagger.hilt.InstallIn import dagger.hilt.android.qualifiers.ApplicationContext import dagger.hilt.components.SingletonComponent import kotlinx.serialization.json.Json +import okhttp3.Call +import okhttp3.OkHttpClient +import okhttp3.logging.HttpLoggingInterceptor import javax.inject.Singleton @Module @@ -41,4 +48,44 @@ object NetworkModule { fun providesFakeAssetManager( @ApplicationContext context: Context, ): FakeAssetManager = FakeAssetManager(context.assets::open) + + @Provides + @Singleton + fun okHttpCallFactory(): Call.Factory = OkHttpClient.Builder() + .addInterceptor( + HttpLoggingInterceptor() + .apply { + if (BuildConfig.DEBUG) { + setLevel(HttpLoggingInterceptor.Level.BODY) + } + } + ) + .build() + + /** + * Since we're displaying SVGs in the app, Coil needs an ImageLoader which supports this + * format. During Coil's initialization it will call `applicationContext.newImageLoader()` to + * obtain an ImageLoader. + * + * @see Coil + */ + @Provides + @Singleton + fun imageLoader( + okHttpCallFactory: Call.Factory, + @ApplicationContext application: Context, + ): ImageLoader = ImageLoader.Builder(application) + .callFactory(okHttpCallFactory) + .components { + add(SvgDecoder.Factory()) + } + // Assume most content images are versioned urls + // but some problematic images are fetching each time + .respectCacheHeaders(false) + .apply { + if (BuildConfig.DEBUG) { + logger(DebugLogger()) + } + } + .build() } diff --git a/core/network/src/main/java/com/google/samples/apps/nowinandroid/core/network/retrofit/RetrofitNiaNetwork.kt b/core/network/src/main/java/com/google/samples/apps/nowinandroid/core/network/retrofit/RetrofitNiaNetwork.kt index 6b59f16e3..7f2f9d6a1 100644 --- a/core/network/src/main/java/com/google/samples/apps/nowinandroid/core/network/retrofit/RetrofitNiaNetwork.kt +++ b/core/network/src/main/java/com/google/samples/apps/nowinandroid/core/network/retrofit/RetrofitNiaNetwork.kt @@ -25,9 +25,8 @@ import com.jakewharton.retrofit2.converter.kotlinx.serialization.asConverterFact import kotlinx.serialization.ExperimentalSerializationApi import kotlinx.serialization.Serializable import kotlinx.serialization.json.Json +import okhttp3.Call import okhttp3.MediaType.Companion.toMediaType -import okhttp3.OkHttpClient -import okhttp3.logging.HttpLoggingInterceptor import retrofit2.Retrofit import retrofit2.http.GET import retrofit2.http.Query @@ -69,26 +68,19 @@ private data class NetworkResponse( val data: T, ) + /** * [Retrofit] backed [NiaNetworkDataSource] */ @Singleton class RetrofitNiaNetwork @Inject constructor( networkJson: Json, + okhttpCallFactory: Call.Factory ) : NiaNetworkDataSource { private val networkApi = Retrofit.Builder() .baseUrl(NiaBaseUrl) - .client( - OkHttpClient.Builder() - .addInterceptor( - // TODO: Decide logging logic - HttpLoggingInterceptor().apply { - setLevel(HttpLoggingInterceptor.Level.BODY) - }, - ) - .build(), - ) + .callFactory(okhttpCallFactory) .addConverterFactory( @OptIn(ExperimentalSerializationApi::class) networkJson.asConverterFactory("application/json".toMediaType()), From 4fa730098df201b4154e038aca0afdc08660cf44 Mon Sep 17 00:00:00 2001 From: Yuri Schimke Date: Sat, 11 Feb 2023 10:39:56 +0000 Subject: [PATCH 2/2] Fixes Change-Id: Iedcafbf0ad7b853544b7b5b3f37685a0a868c2e6 --- .../samples/apps/nowinandroid/core/network/di/NetworkModule.kt | 2 +- .../nowinandroid/core/network/retrofit/RetrofitNiaNetwork.kt | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/core/network/src/main/java/com/google/samples/apps/nowinandroid/core/network/di/NetworkModule.kt b/core/network/src/main/java/com/google/samples/apps/nowinandroid/core/network/di/NetworkModule.kt index d52428f57..98534ba93 100644 --- a/core/network/src/main/java/com/google/samples/apps/nowinandroid/core/network/di/NetworkModule.kt +++ b/core/network/src/main/java/com/google/samples/apps/nowinandroid/core/network/di/NetworkModule.kt @@ -58,7 +58,7 @@ object NetworkModule { if (BuildConfig.DEBUG) { setLevel(HttpLoggingInterceptor.Level.BODY) } - } + }, ) .build() diff --git a/core/network/src/main/java/com/google/samples/apps/nowinandroid/core/network/retrofit/RetrofitNiaNetwork.kt b/core/network/src/main/java/com/google/samples/apps/nowinandroid/core/network/retrofit/RetrofitNiaNetwork.kt index 7f2f9d6a1..9360d2cf1 100644 --- a/core/network/src/main/java/com/google/samples/apps/nowinandroid/core/network/retrofit/RetrofitNiaNetwork.kt +++ b/core/network/src/main/java/com/google/samples/apps/nowinandroid/core/network/retrofit/RetrofitNiaNetwork.kt @@ -68,14 +68,13 @@ private data class NetworkResponse( val data: T, ) - /** * [Retrofit] backed [NiaNetworkDataSource] */ @Singleton class RetrofitNiaNetwork @Inject constructor( networkJson: Json, - okhttpCallFactory: Call.Factory + okhttpCallFactory: Call.Factory, ) : NiaNetworkDataSource { private val networkApi = Retrofit.Builder()