Improve network pooling and avoid startup image fetches.

Change-Id: If747fb0833d31ce7c9bedffd400160e979bc945e
pull/582/head
Yuri Schimke 2 years ago
parent 803e64be53
commit 9e399b69ea

@ -129,7 +129,6 @@ dependencies {
implementation(libs.androidx.profileinstaller) implementation(libs.androidx.profileinstaller)
implementation(libs.coil.kt) implementation(libs.coil.kt)
implementation(libs.coil.kt.svg)
} }
// androidx.test is forcing JUnit, 4.12. This forces it to use 4.13 // androidx.test is forcing JUnit, 4.12. This forces it to use 4.13

@ -19,33 +19,24 @@ package com.google.samples.apps.nowinandroid
import android.app.Application import android.app.Application
import coil.ImageLoader import coil.ImageLoader
import coil.ImageLoaderFactory import coil.ImageLoaderFactory
import coil.decode.SvgDecoder
import com.google.samples.apps.nowinandroid.sync.initializers.Sync import com.google.samples.apps.nowinandroid.sync.initializers.Sync
import dagger.hilt.android.HiltAndroidApp import dagger.hilt.android.HiltAndroidApp
import javax.inject.Inject
import javax.inject.Provider
/** /**
* [Application] class for NiA * [Application] class for NiA
*/ */
@HiltAndroidApp @HiltAndroidApp
class NiaApplication : Application(), ImageLoaderFactory { class NiaApplication : Application(), ImageLoaderFactory {
@Inject
lateinit var imageLoader: Provider<ImageLoader>
override fun onCreate() { override fun onCreate() {
super.onCreate() super.onCreate()
// Initialize Sync; the system responsible for keeping data in the app up to date. // Initialize Sync; the system responsible for keeping data in the app up to date.
Sync.initialize(context = this) Sync.initialize(context = this)
} }
/** override fun newImageLoader(): ImageLoader = imageLoader.get()
* 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 <a href="https://github.com/coil-kt/coil/blob/main/coil-singleton/src/main/java/coil/Coil.kt">Coil</a>
*/
override fun newImageLoader(): ImageLoader {
return ImageLoader.Builder(this)
.components {
add(SvgDecoder.Factory())
}
.build()
}
} }

@ -51,4 +51,7 @@ dependencies {
implementation(libs.okhttp.logging) implementation(libs.okhttp.logging)
implementation(libs.retrofit.core) implementation(libs.retrofit.core)
implementation(libs.retrofit.kotlin.serialization) implementation(libs.retrofit.kotlin.serialization)
implementation(libs.coil.kt)
implementation(libs.coil.kt.svg)
} }

@ -17,6 +17,10 @@
package com.google.samples.apps.nowinandroid.core.network.di package com.google.samples.apps.nowinandroid.core.network.di
import android.content.Context 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 com.google.samples.apps.nowinandroid.core.network.fake.FakeAssetManager
import dagger.Module import dagger.Module
import dagger.Provides import dagger.Provides
@ -24,6 +28,9 @@ import dagger.hilt.InstallIn
import dagger.hilt.android.qualifiers.ApplicationContext import dagger.hilt.android.qualifiers.ApplicationContext
import dagger.hilt.components.SingletonComponent import dagger.hilt.components.SingletonComponent
import kotlinx.serialization.json.Json import kotlinx.serialization.json.Json
import okhttp3.Call
import okhttp3.OkHttpClient
import okhttp3.logging.HttpLoggingInterceptor
import javax.inject.Singleton import javax.inject.Singleton
@Module @Module
@ -41,4 +48,44 @@ object NetworkModule {
fun providesFakeAssetManager( fun providesFakeAssetManager(
@ApplicationContext context: Context, @ApplicationContext context: Context,
): FakeAssetManager = FakeAssetManager(context.assets::open) ): 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 <a href="https://github.com/coil-kt/coil/blob/main/coil-singleton/src/main/java/coil/Coil.kt">Coil</a>
*/
@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()
} }

@ -25,9 +25,8 @@ import com.jakewharton.retrofit2.converter.kotlinx.serialization.asConverterFact
import kotlinx.serialization.ExperimentalSerializationApi import kotlinx.serialization.ExperimentalSerializationApi
import kotlinx.serialization.Serializable import kotlinx.serialization.Serializable
import kotlinx.serialization.json.Json import kotlinx.serialization.json.Json
import okhttp3.Call
import okhttp3.MediaType.Companion.toMediaType import okhttp3.MediaType.Companion.toMediaType
import okhttp3.OkHttpClient
import okhttp3.logging.HttpLoggingInterceptor
import retrofit2.Retrofit import retrofit2.Retrofit
import retrofit2.http.GET import retrofit2.http.GET
import retrofit2.http.Query import retrofit2.http.Query
@ -69,26 +68,19 @@ private data class NetworkResponse<T>(
val data: T, val data: T,
) )
/** /**
* [Retrofit] backed [NiaNetworkDataSource] * [Retrofit] backed [NiaNetworkDataSource]
*/ */
@Singleton @Singleton
class RetrofitNiaNetwork @Inject constructor( class RetrofitNiaNetwork @Inject constructor(
networkJson: Json, networkJson: Json,
okhttpCallFactory: Call.Factory
) : NiaNetworkDataSource { ) : NiaNetworkDataSource {
private val networkApi = Retrofit.Builder() private val networkApi = Retrofit.Builder()
.baseUrl(NiaBaseUrl) .baseUrl(NiaBaseUrl)
.client( .callFactory(okhttpCallFactory)
OkHttpClient.Builder()
.addInterceptor(
// TODO: Decide logging logic
HttpLoggingInterceptor().apply {
setLevel(HttpLoggingInterceptor.Level.BODY)
},
)
.build(),
)
.addConverterFactory( .addConverterFactory(
@OptIn(ExperimentalSerializationApi::class) @OptIn(ExperimentalSerializationApi::class)
networkJson.asConverterFactory("application/json".toMediaType()), networkJson.asConverterFactory("application/json".toMediaType()),

Loading…
Cancel
Save