model: switch from kotlinx to square

Signed-off-by: Harsh Shandilya <me@msfjarvis.dev>
This commit is contained in:
Harsh Shandilya 2020-12-17 11:15:13 +05:30
parent e93e6f0061
commit 3641cd81cd
No known key found for this signature in database
GPG key ID: 366D7BBAD1031E80
10 changed files with 109 additions and 110 deletions

View file

@ -1,16 +0,0 @@
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

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

View file

@ -0,0 +1,44 @@
package dev.msfjarvis.lobsters.injection
import com.squareup.moshi.Moshi
import dagger.Module
import dagger.Lazy
import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.android.components.ActivityComponent
import dev.msfjarvis.lobsters.data.api.LobstersApi
import okhttp3.OkHttpClient
import retrofit2.Retrofit
import retrofit2.converter.moshi.MoshiConverterFactory
import retrofit2.create
@Module
@InstallIn(ActivityComponent::class)
object ApiModule {
@Provides
fun provideClient(): OkHttpClient {
return OkHttpClient.Builder()
.build()
}
/**
* Using [Lazy] here is a trick I picked up from Zac Sweers, which he explained in more
* detail here: https://www.zacsweers.dev/dagger-party-tricks-deferred-okhttp-init/
*/
@Provides
fun provideRetrofit(
client: Lazy<OkHttpClient>,
moshi: Lazy<Moshi>,
): Retrofit {
return Retrofit.Builder()
.client(client.get())
.baseUrl(LobstersApi.BASE_URL)
.addConverterFactory(MoshiConverterFactory.create(moshi.get()))
.build()
}
@Provides
fun provideApi(retrofit: Retrofit): LobstersApi {
return retrofit.create()
}
}

View file

@ -1,14 +0,0 @@
package dev.msfjarvis.lobsters.injection
import dagger.Binds
import dagger.Module
import dagger.hilt.InstallIn
import dagger.hilt.android.components.ActivityComponent
import dev.msfjarvis.lobsters.data.api.KtorLobstersApi
import dev.msfjarvis.lobsters.data.api.LobstersApi
@Module
@InstallIn(ActivityComponent::class)
abstract class KtorApiModule {
@Binds abstract fun bindLobstersApi(realApi: KtorLobstersApi): LobstersApi
}

View file

@ -1,26 +0,0 @@
package dev.msfjarvis.lobsters.injection
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.components.SingletonComponent
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(SingletonComponent::class)
object KtorClientModule {
@Provides
fun provideClient() = HttpClient(OkHttp) {
install(JsonFeature) {
serializer = KotlinxSerializer()
}
engine {
config {
followSslRedirects(true)
}
}
}
}

View file

@ -0,0 +1,16 @@
package dev.msfjarvis.lobsters.injection
import com.squareup.moshi.Moshi
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.components.SingletonComponent
@Module
@InstallIn(SingletonComponent::class)
object MoshiModule {
@Provides
fun provideMoshi(): Moshi {
return Moshi.Builder().build()
}
}

View file

@ -1,12 +1,12 @@
package dev.msfjarvis.lobsters.model
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
import com.squareup.moshi.Json
import com.squareup.moshi.JsonClass
@Serializable
@JsonClass(generateAdapter = true)
class KeybaseSignature(
@SerialName("kb_username")
@Json(name = "kb_username")
val kbUsername: String,
@SerialName("sig_hash")
@Json(name = "sig_hash")
val sigHash: String
)

View file

@ -1,26 +1,26 @@
package dev.msfjarvis.lobsters.model
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
import com.squareup.moshi.Json
import com.squareup.moshi.JsonClass
@Serializable
@JsonClass(generateAdapter = true)
class LobstersPost(
@SerialName("short_id")
@Json(name = "short_id")
val shortId: String,
@SerialName("short_id_url")
@Json(name = "short_id_url")
val shortIdUrl: String,
@SerialName("created_at")
@Json(name = "created_at")
val createdAt: String,
val title: String,
val url: String,
val score: Long,
val flags: Long,
@SerialName("comment_count")
@Json(name = "comment_count")
val commentCount: Long,
val description: String,
@SerialName("comments_url")
@Json(name = "comments_url")
val commentsUrl: String,
@SerialName("submitter_user")
@Json(name = "submitter_user")
val submitterUser: Submitter,
val tags: List<String>,
)

View file

@ -1,27 +1,27 @@
package dev.msfjarvis.lobsters.model
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
import com.squareup.moshi.Json
import com.squareup.moshi.JsonClass
@Serializable
@JsonClass(generateAdapter = true)
class Submitter(
val username: String,
@SerialName("created_at")
@Json(name = "created_at")
val createdAt: String,
@SerialName("is_admin")
@Json(name = "is_admin")
val isAdmin: Boolean,
val about: String,
@SerialName("is_moderator")
@Json(name = "is_moderator")
val isModerator: Boolean,
val karma: Long = 0,
@SerialName("avatar_url")
@Json(name = "avatar_url")
val avatarUrl: String,
@SerialName("invited_by_user")
@Json(name = "invited_by_user")
val invitedByUser: String,
@SerialName("github_username")
@Json(name = "github_username")
val githubUsername: String? = null,
@SerialName("twitter_username")
@Json(name = "twitter_username")
val twitterUsername: String? = null,
@SerialName("keybase_signatures")
@Json(name = "keybase_signatures")
val keybaseSignatures: List<KeybaseSignature> = emptyList()
)

View file

@ -1,54 +1,46 @@
package dev.msfjarvis.lobsters.data.api
import dev.msfjarvis.lobsters.injection.ApiModule
import dev.msfjarvis.lobsters.injection.MoshiModule
import dev.msfjarvis.lobsters.util.TestUtils
import io.ktor.client.HttpClient
import io.ktor.client.engine.mock.MockEngine
import io.ktor.client.engine.mock.respond
import io.ktor.client.features.json.JsonFeature
import io.ktor.client.features.json.serializer.KotlinxSerializer
import io.ktor.http.fullPath
import io.ktor.http.headersOf
import org.junit.Assert.assertEquals
import org.junit.Assert.assertTrue
import kotlinx.coroutines.runBlocking
import okhttp3.mockwebserver.Dispatcher
import okhttp3.mockwebserver.MockResponse
import okhttp3.mockwebserver.MockWebServer
import okhttp3.mockwebserver.RecordedRequest
import org.junit.AfterClass
import org.junit.BeforeClass
import org.junit.Test
class KtorLobstersApiTest {
class LobstersApiTest {
companion object {
@JvmStatic
private lateinit var client: HttpClient
@JvmStatic
private lateinit var apiClient: LobstersApi
private val webServer = MockWebServer()
private val apiData = TestUtils.getJson("hottest.json")
private val okHttp = ApiModule.provideClient()
private val retrofit = ApiModule.provideRetrofit(
{ okHttp },
{ MoshiModule.provideMoshi() }
)
private val apiClient = ApiModule.provideApi(retrofit)
@JvmStatic
@BeforeClass
fun setUp() {
client = HttpClient(MockEngine) {
install(JsonFeature) {
serializer = KotlinxSerializer()
webServer.start(8080)
webServer.dispatcher = object : Dispatcher() {
override fun dispatch(request: RecordedRequest): MockResponse {
return MockResponse().setBody(apiData).setResponseCode(200)
}
engine {
addHandler { request ->
when (request.url.fullPath) {
"/hottest.json?page=1" -> {
val responseHeaders = headersOf("Content-Type" to listOf("application/json"))
respond(TestUtils.getJson("hottest.json"), headers = responseHeaders)
}
else -> error("Unhandled ${request.url.fullPath}")
}
}
}
}
apiClient = KtorLobstersApi(client)
}
@JvmStatic
@AfterClass
fun tearDown() {
client.close()
webServer.shutdown()
}
}