Skip to content

Commit 283eeff

Browse files
committed
refactor: implement HttpClient as a singleton
1 parent a4d12cb commit 283eeff

File tree

3 files changed

+46
-37
lines changed

3 files changed

+46
-37
lines changed
Lines changed: 1 addition & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,9 @@
11
package com.coderGtm.yantra.commands.weather
22

3-
import android.util.Log
4-
import com.coderGtm.yantra.BuildConfig
53
import com.coderGtm.yantra.R
64
import com.coderGtm.yantra.blueprints.BaseCommand
75
import com.coderGtm.yantra.models.CommandMetadata
86
import com.coderGtm.yantra.terminal.Terminal
9-
import io.ktor.client.HttpClient
10-
import io.ktor.client.engine.android.Android
11-
import io.ktor.client.plugins.contentnegotiation.ContentNegotiation
12-
import io.ktor.client.plugins.logging.LogLevel
13-
import io.ktor.client.plugins.logging.Logging
14-
import io.ktor.serialization.kotlinx.json.json
15-
import io.ktor.util.logging.Logger
16-
import kotlinx.serialization.json.Json
177

188
class Command(terminal: Terminal) : BaseCommand(terminal) {
199
override val metadata = CommandMetadata(
@@ -22,28 +12,6 @@ class Command(terminal: Terminal) : BaseCommand(terminal) {
2212
description = terminal.activity.getString(R.string.cmd_weather_help)
2313
)
2414

25-
// todo: ideally this would be a singleton that is re-used across the app
26-
private val httpClient = HttpClient(Android) {
27-
expectSuccess = true
28-
29-
install(ContentNegotiation) {
30-
json(Json {
31-
ignoreUnknownKeys = true
32-
coerceInputValues = true
33-
})
34-
}
35-
if (BuildConfig.DEBUG) {
36-
install(Logging) {
37-
logger = object : io.ktor.client.plugins.logging.Logger {
38-
override fun log(message: String) {
39-
Log.d("HTTP call", message)
40-
}
41-
}
42-
level = LogLevel.ALL
43-
}
44-
}
45-
46-
}
4715

4816
override fun execute(command: String) {
4917
when (val parseResult = parseWeatherCommand(command, this.terminal.activity)) {
@@ -55,7 +23,7 @@ class Command(terminal: Terminal) : BaseCommand(terminal) {
5523
)
5624

5725
is ParseResult.ListCommand -> showAvailableFields(this)
58-
is ParseResult.Success -> fetchWeatherData(parseResult.args, this, httpClient)
26+
is ParseResult.Success -> fetchWeatherData(parseResult.args, this)
5927
}
6028
}
6129
}

app/src/main/java/com/coderGtm/yantra/commands/weather/Helper.kt

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import android.graphics.Typeface
55
import androidx.appcompat.app.AppCompatDelegate
66
import com.coderGtm.yantra.R
77
import com.coderGtm.yantra.blueprints.BaseCommand
8-
import io.ktor.client.HttpClient
8+
import com.coderGtm.yantra.network.HttpClientProvider
99
import io.ktor.client.call.body
1010
import io.ktor.client.plugins.ClientRequestException
1111
import io.ktor.client.request.get
@@ -26,9 +26,8 @@ private var weatherJob: Job? = null
2626
*
2727
* @param args The [WeatherCommandArgs] containing the location for which to fetch weather data.
2828
* @param command The [BaseCommand] instance.
29-
* @param httpClient The [HttpClient] instance used to make the network request.
3029
*/
31-
fun fetchWeatherData(args: WeatherCommandArgs, command: BaseCommand, httpClient: HttpClient) {
30+
fun fetchWeatherData(args: WeatherCommandArgs, command: BaseCommand) {
3231
val location = args.location
3332

3433
val langCode = AppCompatDelegate.getApplicationLocales().toLanguageTags()
@@ -51,7 +50,7 @@ fun fetchWeatherData(args: WeatherCommandArgs, command: BaseCommand, httpClient:
5150
try {
5251
ensureActive()
5352
val weather = withContext(Dispatchers.IO) {
54-
httpClient.get(url).body<WeatherResponse>()
53+
HttpClientProvider.client.get(url).body<WeatherResponse>()
5554
}
5655
handleResponse(weather, args, command)
5756
} catch (e: Exception) {
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
package com.coderGtm.yantra.network
2+
3+
import android.util.Log
4+
import com.coderGtm.yantra.BuildConfig
5+
import io.ktor.client.HttpClient
6+
import io.ktor.client.engine.android.Android
7+
import io.ktor.client.plugins.contentnegotiation.ContentNegotiation
8+
import io.ktor.client.plugins.logging.LogLevel
9+
import io.ktor.client.plugins.logging.Logging
10+
import io.ktor.serialization.kotlinx.json.json
11+
import kotlinx.serialization.json.Json
12+
13+
/**
14+
* Provides a singleton HttpClient instance for the application.
15+
* This ensures efficient resource usage and connection pool reuse across all network requests.
16+
*/
17+
object HttpClientProvider {
18+
19+
val client: HttpClient by lazy {
20+
HttpClient(Android) {
21+
expectSuccess = true
22+
23+
install(ContentNegotiation) {
24+
json(Json {
25+
ignoreUnknownKeys = true
26+
coerceInputValues = true
27+
})
28+
}
29+
30+
if (BuildConfig.DEBUG) {
31+
install(Logging) {
32+
logger = object : io.ktor.client.plugins.logging.Logger {
33+
override fun log(message: String) {
34+
Log.d("HTTP call", message)
35+
}
36+
}
37+
level = LogLevel.ALL
38+
}
39+
}
40+
}
41+
}
42+
}

0 commit comments

Comments
 (0)