app: reinstate API wrapper to hide client implementation

Signed-off-by: Harsh Shandilya <me@msfjarvis.dev>
This commit is contained in:
Harsh Shandilya 2020-11-08 16:41:02 +05:30
parent 5b77fdf54b
commit 276877119d
No known key found for this signature in database
GPG key ID: 366D7BBAD1031E80
6 changed files with 75 additions and 23 deletions

View file

@ -8,3 +8,11 @@
-keepclasseswithmembers class dev.msfjarvis.lobsters.model.** {
kotlinx.serialization.KSerializer serializer(...);
}
# Workaround for https://github.com/ktorio/ktor/issues/1354
-keepclassmembers class io.ktor.** { volatile <fields>; }
# Workaround for https://github.com/Kotlin/kotlinx.coroutines/issues/1564
-keepclassmembers class kotlinx.** {
volatile <fields>;
}

View file

@ -0,0 +1,16 @@
package dev.msfjarvis.lobsters.data.api
import dev.msfjarvis.lobsters.data.api.LobstersApi.Companion.BASE_URL
import dev.msfjarvis.lobsters.model.LobstersPost
import io.ktor.client.HttpClient
import io.ktor.client.request.get
import javax.inject.Inject
/**
* Ktor backed implementation of [LobstersApi]
*/
class KtorLobstersApi @Inject constructor(private val client: HttpClient) : LobstersApi {
override suspend fun getHottestPosts(page: Int): List<LobstersPost> {
return client.get("${BASE_URL}/hottest.json?page=$page")
}
}

View file

@ -0,0 +1,15 @@
package dev.msfjarvis.lobsters.data.api
import dev.msfjarvis.lobsters.model.LobstersPost
/**
* Simple interface defining an API for lobste.rs
*/
interface LobstersApi {
suspend fun getHottestPosts(page: Int): List<LobstersPost>
companion object {
const val BASE_URL = "https://lobste.rs"
}
}

View file

@ -1,26 +1,14 @@
package dev.msfjarvis.lobsters.injection
import dagger.Binds
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.android.components.ApplicationComponent
import io.ktor.client.HttpClient
import io.ktor.client.engine.okhttp.OkHttp
import io.ktor.client.features.json.JsonFeature
import io.ktor.client.features.json.serializer.KotlinxSerializer
import dagger.hilt.android.components.ActivityComponent
import dev.msfjarvis.lobsters.data.api.KtorLobstersApi
import dev.msfjarvis.lobsters.data.api.LobstersApi
@Module
@InstallIn(ApplicationComponent::class)
object KtorApiModule {
@Provides
fun provideClient() = HttpClient(OkHttp) {
install(JsonFeature) {
serializer = KotlinxSerializer()
}
engine {
config {
followSslRedirects(true)
}
}
}
@InstallIn(ActivityComponent::class)
abstract class KtorApiModule {
@Binds abstract fun bindLobstersApi(realApi: KtorLobstersApi): LobstersApi
}

View file

@ -0,0 +1,26 @@
package dev.msfjarvis.lobsters.injection
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.android.components.ApplicationComponent
import io.ktor.client.HttpClient
import io.ktor.client.engine.okhttp.OkHttp
import io.ktor.client.features.json.JsonFeature
import io.ktor.client.features.json.serializer.KotlinxSerializer
@Module
@InstallIn(ApplicationComponent::class)
object KtorClientModule {
@Provides
fun provideClient() = HttpClient(OkHttp) {
install(JsonFeature) {
serializer = KotlinxSerializer()
}
engine {
config {
followSslRedirects(true)
}
}
}
}

View file

@ -3,10 +3,9 @@ package dev.msfjarvis.lobsters.ui.viewmodel
import androidx.hilt.lifecycle.ViewModelInject
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import dev.msfjarvis.lobsters.data.api.LobstersApi
import dev.msfjarvis.lobsters.data.source.PostsDatabase
import dev.msfjarvis.lobsters.model.LobstersPost
import io.ktor.client.HttpClient
import io.ktor.client.request.get
import kotlinx.coroutines.CoroutineExceptionHandler
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
@ -16,7 +15,7 @@ import java.net.SocketTimeoutException
import java.net.UnknownHostException
class LobstersViewModel @ViewModelInject constructor(
private val client: HttpClient,
private val lobstersApi: LobstersApi,
database: PostsDatabase,
) : ViewModel() {
private var apiPage = 1
@ -57,7 +56,7 @@ class LobstersViewModel @ViewModelInject constructor(
private fun getMorePostsInternal(firstLoad: Boolean) {
viewModelScope.launch(coroutineExceptionHandler) {
val newPosts = client.get<List<LobstersPost>>("https://lobste.rs/hottest.json?page=$apiPage")
val newPosts = lobstersApi.getHottestPosts(apiPage)
if (firstLoad) {
_posts.value = newPosts
postsDao.deleteAllPosts()