diff --git a/.idea/deploymentTargetDropDown.xml b/.idea/deploymentTargetDropDown.xml
index 2956c3f..767547e 100644
--- a/.idea/deploymentTargetDropDown.xml
+++ b/.idea/deploymentTargetDropDown.xml
@@ -12,6 +12,6 @@
-
+
\ No newline at end of file
diff --git a/app/build.gradle b/app/build.gradle
index 8fe89da..28020af 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -4,6 +4,7 @@ plugins {
id 'kotlin-kapt'
id 'com.google.dagger.hilt.android'
id 'maven-publish'
+ id 'kotlinx-serialization'
}
android {
@@ -90,4 +91,6 @@ dependencies {
kapt "com.google.dagger:hilt-compiler:2.44.2"
implementation 'androidx.lifecycle:lifecycle-runtime-compose:2.6.0-alpha01'
+
+ implementation 'org.jetbrains.kotlinx:kotlinx-serialization-json:1.5.1'
}
\ No newline at end of file
diff --git a/app/src/main/java/com/jeremy/thunder/di/SocketModule.kt b/app/src/main/java/com/jeremy/thunder/di/SocketModule.kt
index 0e41a61..a997fd1 100644
--- a/app/src/main/java/com/jeremy/thunder/di/SocketModule.kt
+++ b/app/src/main/java/com/jeremy/thunder/di/SocketModule.kt
@@ -1,7 +1,7 @@
package com.jeremy.thunder.di
import android.content.Context
-import com.jeremy.thunder.Thunder
+import com.jeremy.thunder.event.converter.ConverterType
import com.jeremy.thunder.makeWebSocketCore
import com.jeremy.thunder.socket.SocketService
import com.jeremy.thunder.thunder
@@ -37,6 +37,7 @@ internal object SocketModule {
return thunder {
webSocketCore(okHttpClient.makeWebSocketCore("wss://fstream.binance.com/stream"))
setApplicationContext(context)
+ setConverterType(ConverterType.Serialization)
}.create()
}
}
\ No newline at end of file
diff --git a/app/src/main/java/com/jeremy/thunder/socket/model/AllMarketTickerResponse.kt b/app/src/main/java/com/jeremy/thunder/socket/model/AllMarketTickerResponse.kt
index fbcc565..c464bfc 100644
--- a/app/src/main/java/com/jeremy/thunder/socket/model/AllMarketTickerResponse.kt
+++ b/app/src/main/java/com/jeremy/thunder/socket/model/AllMarketTickerResponse.kt
@@ -1,13 +1,17 @@
package com.jeremy.thunder.socket.model
import com.google.gson.annotations.SerializedName
+import kotlinx.serialization.Serializable
+@Serializable
data class AllMarketTickerResponse(
- @SerializedName("stream")
+ //@SerializedName("stream")
val stream: String = "",
- @SerializedName("data")
- val data: List = emptyList()
+ //@SerializedName("data")
+ val data: List = emptyList(),
+
+ val nickName: String = "default"
)
/*
@@ -38,25 +42,28 @@ data class AllMarketTickerResponse(
*
* */
+@Serializable
data class AllMarketTickerResponseItem(
- @SerializedName("E")
+ //@SerializedName("E")
val E: Long, //event time
- @SerializedName("P")
+ val e: String,
+
+ //@SerializedName("P")
val P: String, // price change percent
- @SerializedName("c")
+ //@SerializedName("c")
val c: String, // last Price
- @SerializedName("h")
+ //@SerializedName("h")
val h: String, // high price
- @SerializedName("l")
+ //@SerializedName("l")
val l: String, // low price
- @SerializedName("o")
+ //@SerializedName("o")
val o: String, // open price
- @SerializedName("s")
+// @SerializedName("s")
val s: String, // symbol
)
diff --git a/build.gradle b/build.gradle
index c0b7e96..14e4932 100644
--- a/build.gradle
+++ b/build.gradle
@@ -10,6 +10,8 @@ plugins {
id 'org.jetbrains.kotlin.android' version '1.8.10' apply false
id 'com.android.library' version '7.4.2' apply false
id 'com.google.dagger.hilt.android' version '2.44.2' apply false
+ id 'org.jetbrains.kotlin.jvm' version '1.8.10' apply false
+ id 'org.jetbrains.kotlin.plugin.serialization' version '1.8.10' apply false
}
task clean(type: Delete) {
diff --git a/thunder/build.gradle b/thunder/build.gradle
index 00f8d45..51ac17a 100644
--- a/thunder/build.gradle
+++ b/thunder/build.gradle
@@ -58,4 +58,6 @@ dependencies {
implementation 'com.squareup.okhttp3:logging-interceptor:4.9.2'
implementation 'com.google.code.gson:gson:2.9.0'
+
+ implementation 'org.jetbrains.kotlinx:kotlinx-serialization-json:1.5.1'
}
\ No newline at end of file
diff --git a/thunder/src/main/java/com/jeremy/thunder/Thunder.kt b/thunder/src/main/java/com/jeremy/thunder/Thunder.kt
index 6bb2036..d69bc3d 100644
--- a/thunder/src/main/java/com/jeremy/thunder/Thunder.kt
+++ b/thunder/src/main/java/com/jeremy/thunder/Thunder.kt
@@ -8,6 +8,7 @@ import com.jeremy.thunder.coroutine.CoroutineScope.scope
import com.jeremy.thunder.event.EventProcessor
import com.jeremy.thunder.event.WebSocketEvent
import com.jeremy.thunder.event.WebSocketEventProcessor
+import com.jeremy.thunder.event.converter.ConverterType
import com.jeremy.thunder.internal.ServiceExecutor
import com.jeremy.thunder.internal.ThunderProvider
import com.jeremy.thunder.internal.ThunderStateManager
@@ -57,6 +58,7 @@ class Thunder private constructor(
private var thunderStateManager: ThunderStateManager? = null
private var context: Context? = null
private val appConnectionProvider by lazy { AppConnectionProvider() }
+ private var converterType: ConverterType = ConverterType.Serialization
fun webSocketCore(core: WebSocket.Factory): Builder = apply { this.webSocketCore = core }
@@ -65,6 +67,10 @@ class Thunder private constructor(
(this.context as Application).registerActivityLifecycleCallbacks(appConnectionProvider)
}
+ fun setConverterType(type: ConverterType) = apply {
+ converterType = type
+ }
+
private fun createThunderStateManager(): ThunderStateManager {
thunderStateManager = ThunderStateManager.Factory(
connectionListener = appConnectionProvider,
@@ -101,6 +107,7 @@ class Thunder private constructor(
private fun createServiceExecutor(): ServiceExecutor {
return ServiceExecutor.Factory(
thunderProvider = createThunderProvider(),
+ converterType = converterType,
scope = scope
).create()
}
diff --git a/thunder/src/main/java/com/jeremy/thunder/event/EventMapper.kt b/thunder/src/main/java/com/jeremy/thunder/event/EventMapper.kt
index ddf1ba2..1c4305f 100644
--- a/thunder/src/main/java/com/jeremy/thunder/event/EventMapper.kt
+++ b/thunder/src/main/java/com/jeremy/thunder/event/EventMapper.kt
@@ -1,5 +1,6 @@
package com.jeremy.thunder.event
+import com.jeremy.thunder.event.converter.Converter
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.filter
import kotlinx.coroutines.flow.map
diff --git a/thunder/src/main/java/com/jeremy/thunder/event/SocketEventKeyStore.kt b/thunder/src/main/java/com/jeremy/thunder/event/SocketEventKeyStore.kt
index e48bd56..00728b4 100644
--- a/thunder/src/main/java/com/jeremy/thunder/event/SocketEventKeyStore.kt
+++ b/thunder/src/main/java/com/jeremy/thunder/event/SocketEventKeyStore.kt
@@ -1,5 +1,6 @@
package com.jeremy.thunder.event
+import com.jeremy.thunder.event.converter.Converter
import java.lang.reflect.Type
/**
diff --git a/thunder/src/main/java/com/jeremy/thunder/event/converter/Converter.kt b/thunder/src/main/java/com/jeremy/thunder/event/converter/Converter.kt
new file mode 100644
index 0000000..61ddf2b
--- /dev/null
+++ b/thunder/src/main/java/com/jeremy/thunder/event/converter/Converter.kt
@@ -0,0 +1,5 @@
+package com.jeremy.thunder.event.converter
+
+interface Converter {
+ fun convert(data: String): T
+}
\ No newline at end of file
diff --git a/thunder/src/main/java/com/jeremy/thunder/event/converter/ConverterType.kt b/thunder/src/main/java/com/jeremy/thunder/event/converter/ConverterType.kt
new file mode 100644
index 0000000..6b4b5bd
--- /dev/null
+++ b/thunder/src/main/java/com/jeremy/thunder/event/converter/ConverterType.kt
@@ -0,0 +1,7 @@
+package com.jeremy.thunder.event.converter
+
+sealed class ConverterType {
+ object Gson: ConverterType()
+
+ object Serialization: ConverterType()
+}
\ No newline at end of file
diff --git a/thunder/src/main/java/com/jeremy/thunder/event/Converter.kt b/thunder/src/main/java/com/jeremy/thunder/event/converter/GsonConvertAdapter.kt
similarity index 68%
rename from thunder/src/main/java/com/jeremy/thunder/event/Converter.kt
rename to thunder/src/main/java/com/jeremy/thunder/event/converter/GsonConvertAdapter.kt
index f75fce0..0d2bfda 100644
--- a/thunder/src/main/java/com/jeremy/thunder/event/Converter.kt
+++ b/thunder/src/main/java/com/jeremy/thunder/event/converter/GsonConvertAdapter.kt
@@ -1,4 +1,4 @@
-package com.jeremy.thunder.event
+package com.jeremy.thunder.event.converter
import com.google.gson.Gson
import com.google.gson.TypeAdapter
@@ -6,11 +6,7 @@ import com.google.gson.reflect.TypeToken
import java.io.StringReader
import java.lang.reflect.Type
-interface Converter {
- fun convert(data: String): T
-}
-
-class ConvertAdapter private constructor(
+class GsonConvertAdapter private constructor(
private val gson: Gson,
private val typeAdapter: TypeAdapter,
private val type: Type
@@ -22,9 +18,9 @@ class ConvertAdapter private constructor(
}
class Factory {
- fun create(type: Type): ConvertAdapter<*> {
+ fun create(type: Type): GsonConvertAdapter<*> {
val typeAdapter = Gson().getAdapter(TypeToken.get(type))
- return ConvertAdapter(Gson(), typeAdapter, type)
+ return GsonConvertAdapter(Gson(), typeAdapter, type)
}
}
}
\ No newline at end of file
diff --git a/thunder/src/main/java/com/jeremy/thunder/event/converter/SerializeConvertAdapter.kt b/thunder/src/main/java/com/jeremy/thunder/event/converter/SerializeConvertAdapter.kt
new file mode 100644
index 0000000..c282866
--- /dev/null
+++ b/thunder/src/main/java/com/jeremy/thunder/event/converter/SerializeConvertAdapter.kt
@@ -0,0 +1,45 @@
+package com.jeremy.thunder.event.converter
+
+import com.jeremy.thunder.thunderLog
+import kotlinx.serialization.DeserializationStrategy
+import kotlinx.serialization.KSerializer
+import kotlinx.serialization.SerialFormat
+import kotlinx.serialization.StringFormat
+import kotlinx.serialization.json.Json
+import kotlinx.serialization.serializer
+import okhttp3.internal.ignoreIoExceptions
+import java.lang.reflect.Type
+
+class SerializeConvertAdapter private constructor(
+ type: Type,
+ private val kSerializer: KSerializer
+) : Converter {
+ private fun SerialFormat.serializeAsType(type: Type): KSerializer = serializersModule.serializer(type)
+ class Factory {
+ fun create(type: Type): SerializeConvertAdapter<*> {
+ return SerializeConvertAdapter(type, serializer(type))
+ }
+ }
+
+ private val json = Json {
+ isLenient = true
+ useAlternativeNames = true // can use alternative key
+ ignoreUnknownKeys = true // prevent ignore no matching key exception
+ coerceInputValues = true // Set as non-null type but receive as null type. you can use default value as set true
+ encodeDefaults = true // You can use default value when received data does not have that value.
+ }
+
+ private val stringFormat: StringFormat = json.apply {
+ ignoreIoExceptions {
+ thunderLog("[IoException] Cause convert specific type is not supported.")
+ }
+ }
+
+ private val loader: DeserializationStrategy = stringFormat.serializeAsType(type) as DeserializationStrategy
+
+ override fun convert(data: String): T {
+ return kotlin.run {
+ stringFormat.decodeFromString(loader, data)
+ }
+ }
+}
diff --git a/thunder/src/main/java/com/jeremy/thunder/internal/ServiceExecutor.kt b/thunder/src/main/java/com/jeremy/thunder/internal/ServiceExecutor.kt
index 2050825..358e759 100644
--- a/thunder/src/main/java/com/jeremy/thunder/internal/ServiceExecutor.kt
+++ b/thunder/src/main/java/com/jeremy/thunder/internal/ServiceExecutor.kt
@@ -1,9 +1,12 @@
package com.jeremy.thunder.internal
import com.google.gson.Gson
-import com.jeremy.thunder.event.ConvertAdapter
import com.jeremy.thunder.event.SocketEventKeyStore
import com.jeremy.thunder.event.WebSocketEvent
+import com.jeremy.thunder.event.converter.Converter
+import com.jeremy.thunder.event.converter.ConverterType
+import com.jeremy.thunder.event.converter.GsonConvertAdapter
+import com.jeremy.thunder.event.converter.SerializeConvertAdapter
import com.jeremy.thunder.getAboutRawType
import com.jeremy.thunder.getParameterUpperBound
import kotlinx.coroutines.CoroutineScope
@@ -14,6 +17,7 @@ import kotlinx.coroutines.flow.map
import kotlinx.coroutines.launch
import java.lang.reflect.Method
import java.lang.reflect.ParameterizedType
+import java.lang.reflect.Type
/**
* create logic by annotation
@@ -23,6 +27,7 @@ import java.lang.reflect.ParameterizedType
class ServiceExecutor internal constructor(
private val thunderProvider: ThunderProvider,
+ private val converterType: ConverterType,
private val scope: CoroutineScope
) {
@@ -49,7 +54,9 @@ class ServiceExecutor internal constructor(
method.requireParameterTypes { "Receive method must have zero parameter: $method" }
method.requireReturnTypeIsOneOf(ParameterizedType::class.java) { "Receive method must return ParameterizedType: $method" }
val returnType = (method.genericReturnType as ParameterizedType).getParameterUpperBound(0)
- val converter = ConvertAdapter.Factory().create(returnType)
+ //val converter = ConvertAdapter.Factory().create(returnType)
+ //val converter = SerializeConvertAdapter.Factory().create(returnType)
+ val converter = checkConverterType(converterType, returnType)
val eventMapper = SocketEventKeyStore().findEventMapper(returnType, method.annotations, converter)
thunderProvider.observeEvent()
.map(eventMapper::mapEvent)
@@ -62,6 +69,13 @@ class ServiceExecutor internal constructor(
}
}
+ private fun checkConverterType(converterType: ConverterType, returnType: Type): Converter {
+ return when(converterType) {
+ ConverterType.Gson -> GsonConvertAdapter.Factory().create(returnType)
+ ConverterType.Serialization -> SerializeConvertAdapter.Factory().create(returnType)
+ }
+ }
+
private fun Flow.createPipeline(): ReceivePipeline<*> = ReceivePipeline(this, scope)
fun executeSend(method: Method, args: Array) {
@@ -74,11 +88,12 @@ class ServiceExecutor internal constructor(
class Factory(
private val thunderProvider: ThunderProvider,
- private val scope: CoroutineScope
+ private val converterType: ConverterType,
+ private val scope: CoroutineScope,
) {
fun create(): ServiceExecutor {
- return ServiceExecutor(thunderProvider, scope)
+ return ServiceExecutor(thunderProvider, converterType, scope)
}
}