Browse Source

完善Demo的数据转换器示例

drake 4 years ago
parent
commit
22383ad5db

+ 1 - 1
sample/src/main/java/com/drake/net/sample/base/App.kt

@@ -46,7 +46,7 @@ class App : Application() {
 
             setRequestInterceptor(object : RequestInterceptor { // 添加请求拦截器
                 override fun interceptor(request: BaseRequest) {
-                    request.param("client", "Net")
+                    request.addHeader("client", "Net")
                     request.setHeader("token", "123456")
                 }
             })

+ 1 - 1
sample/src/main/java/com/drake/net/sample/convert/FastJsonConvert.kt

@@ -20,7 +20,7 @@ import com.alibaba.fastjson.JSON
 import com.drake.net.convert.JSONConvert
 import java.lang.reflect.Type
 
-class FastJsonConvert : JSONConvert(code = "code", message = "msg", success = "200") {
+class FastJsonConvert : JSONConvert(code = "code", message = "msg", success = "0") {
 
     override fun <S> String.parseBody(succeed: Type): S? {
         return JSON.parseObject(this, succeed)

+ 1 - 1
sample/src/main/java/com/drake/net/sample/convert/GsonConvert.kt

@@ -20,7 +20,7 @@ import com.drake.net.convert.JSONConvert
 import com.google.gson.GsonBuilder
 import java.lang.reflect.Type
 
-class GsonConvert : JSONConvert(code = "code", message = "msg", success = "200") {
+class GsonConvert : JSONConvert(code = "code", message = "msg", success = "0") {
     private val gson = GsonBuilder().serializeNulls().create()
 
     override fun <S> String.parseBody(succeed: Type): S? {

+ 1 - 1
sample/src/main/java/com/drake/net/sample/convert/MoshiConvert.kt

@@ -20,7 +20,7 @@ import com.drake.net.convert.JSONConvert
 import com.squareup.moshi.Moshi
 import java.lang.reflect.Type
 
-class MoshiConvert : JSONConvert(code = "code", message = "msg", success = "200") {
+class MoshiConvert : JSONConvert(code = "code", message = "msg", success = "0") {
     private val moshi = Moshi.Builder().build()
 
     override fun <S> String.parseBody(succeed: Type): S? {

+ 60 - 0
sample/src/main/java/com/drake/net/sample/convert/SerializationConvert.kt

@@ -0,0 +1,60 @@
+@file:Suppress("UNCHECKED_CAST")
+
+package com.drake.net.sample.convert
+
+import com.drake.net.NetConfig
+import com.drake.net.convert.NetConverter
+import com.drake.net.exception.ConvertException
+import com.drake.net.exception.RequestParamsException
+import com.drake.net.exception.ResponseException
+import com.drake.net.exception.ServerResponseException
+import com.drake.net.request.kType
+import kotlinx.serialization.SerializationException
+import kotlinx.serialization.json.Json
+import kotlinx.serialization.serializer
+import okhttp3.Response
+import org.json.JSONObject
+import java.lang.reflect.Type
+
+class SerializationConvert(
+    val success: String = "0",
+    val code: String = "code",
+    val message: String = "msg"
+) : NetConverter {
+
+    val jsonDecoder = Json {
+        ignoreUnknownKeys = true // JSON和数据模型字段可以不匹配
+        coerceInputValues = true // 如果JSON字段是Null则使用默认值
+    }
+
+    override fun <R> onConvert(succeed: Type, response: Response): R? {
+        try {
+            return NetConverter.DEFAULT.onConvert<R>(succeed, response)
+        } catch (e: ConvertException) {
+
+            val code = response.code
+            when {
+                code in 200..299 -> { // 请求成功
+                    val body = response.body?.string() ?: return null
+                    if (succeed === String::class.java) return body as R
+                    val jsonObject = JSONObject(body) // 获取JSON中后端定义的错误码和错误信息
+                    if (jsonObject.getString(this.code) == success) { // 对比后端自定义错误码
+                        return run {
+                            val kType = response.request.kType() ?: return null
+                            try {
+                                jsonDecoder.decodeFromString(Json.serializersModule.serializer(kType), jsonObject.getString("data")) as R
+                            } catch (e: SerializationException) {
+                                throw ConvertException(response, cause = e)
+                            }
+                        }
+                    } else { // 错误码匹配失败, 开始写入错误异常
+                        throw ResponseException(response, jsonObject.optString(message, NetConfig.app.getString(com.drake.net.R.string.no_error_message)))
+                    }
+                }
+                code in 400..499 -> throw RequestParamsException(response) // 请求参数错误
+                code >= 500 -> throw ServerResponseException(response) // 服务器异常错误
+                else -> throw ConvertException(response)
+            }
+        }
+    }
+}

+ 0 - 21
sample/src/main/java/com/drake/net/sample/model/ListModel.kt

@@ -1,21 +0,0 @@
-/*
- * Copyright (C) 2018 Drake, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.drake.net.sample.model
-
-data class ListModel(var code: Int, var msg: String, var data: Data) {
-    data class Data(var total: Int, var list: List<String>)
-}

+ 4 - 0
sample/src/main/java/com/drake/net/sample/model/Model.kt

@@ -16,6 +16,10 @@
 
 package com.drake.net.sample.model
 
+import kotlinx.serialization.Serializable
+
+@Serializable
 data class Model(var code: Int, var msg: String, var data: Data) {
+    @Serializable
     data class Data(var request_method: String)
 }

+ 6 - 0
sample/src/main/java/com/drake/net/sample/model/UserModel.kt

@@ -0,0 +1,6 @@
+package com.drake.net.sample.model
+
+import kotlinx.serialization.Serializable
+
+@Serializable
+data class UserModel(var name: String, var age: Int, var height: Int)

+ 0 - 2
sample/src/main/java/com/drake/net/sample/ui/fragment/RequestMethodFragment.kt

@@ -34,8 +34,6 @@ class RequestMethodFragment : Fragment(R.layout.fragment_request_method) {
 
     override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
         setHasOptionsMenu(true)
-
-        GET()
     }
 
     private fun GET() {

+ 29 - 0
sample/src/main/java/com/drake/net/sample/ui/fragment/converter/BaseConvertFragment.kt

@@ -0,0 +1,29 @@
+package com.drake.net.sample.ui.fragment.converter
+
+import android.os.Bundle
+import android.view.Menu
+import android.view.MenuInflater
+import android.view.MenuItem
+import androidx.annotation.LayoutRes
+import androidx.fragment.app.Fragment
+import androidx.navigation.fragment.findNavController
+import androidx.navigation.ui.onNavDestinationSelected
+import com.drake.net.sample.R
+
+open class BaseConvertFragment(@LayoutRes contentLayoutId: Int = 0) : Fragment(contentLayoutId) {
+
+    override fun onCreate(savedInstanceState: Bundle?) {
+        super.onCreate(savedInstanceState)
+        setHasOptionsMenu(true)
+    }
+
+    override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
+        super.onCreateOptionsMenu(menu, inflater)
+        inflater.inflate(R.menu.menu_converter, menu)
+    }
+
+    override fun onOptionsItemSelected(item: MenuItem): Boolean {
+        item.onNavDestinationSelected(findNavController())
+        return true
+    }
+}

+ 44 - 0
sample/src/main/java/com/drake/net/sample/ui/fragment/converter/FastJsonConvertFragment.kt

@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2018 Drake, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.drake.net.sample.ui.fragment.converter
+
+import android.os.Bundle
+import android.view.View
+import com.drake.net.Get
+import com.drake.net.sample.R
+import com.drake.net.sample.convert.FastJsonConvert
+import com.drake.net.sample.model.Model
+import com.drake.net.utils.scopeNetLife
+import kotlinx.android.synthetic.main.fragment_custom_convert.*
+
+
+class FastJsonConvertFragment : BaseConvertFragment(R.layout.fragment_custom_convert) {
+
+    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
+        tv_convert_tip.text = """
+            1. 阿里巴巴出品的Json解析库
+            2. 引入kotlin-reflect库可以支持kotlin默认值
+        """.trimIndent()
+
+        scopeNetLife {
+            tv_fragment.text = Get<Model>("api") {
+                converter = FastJsonConvert() // 单例转换器, 此时会忽略全局转换器
+            }.await().data.request_method
+        }
+    }
+
+}

+ 9 - 3
sample/src/main/java/com/drake/net/sample/ui/fragment/CustomConvertFragment.kt → sample/src/main/java/com/drake/net/sample/ui/fragment/converter/GsonConvertFragment.kt

@@ -14,11 +14,10 @@
  * limitations under the License.
  */
 
-package com.drake.net.sample.ui.fragment
+package com.drake.net.sample.ui.fragment.converter
 
 import android.os.Bundle
 import android.view.View
-import androidx.fragment.app.Fragment
 import com.drake.net.Get
 import com.drake.net.sample.R
 import com.drake.net.sample.convert.GsonConvert
@@ -27,9 +26,16 @@ import com.drake.net.utils.scopeNetLife
 import kotlinx.android.synthetic.main.fragment_custom_convert.*
 
 
-class CustomConvertFragment : Fragment(R.layout.fragment_custom_convert) {
+class GsonConvertFragment : BaseConvertFragment(R.layout.fragment_custom_convert) {
 
     override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
+        tv_convert_tip.text = """
+            1. Google官方出品
+            2. Json解析库Java上的老牌解析库
+            3. 不支持Kotlin构造参数默认值
+            4. 支持动态解析
+        """.trimIndent()
+
         scopeNetLife {
             tv_fragment.text = Get<Model>("api") {
                 converter = GsonConvert() // 单例转换器, 此时会忽略全局转换器

+ 46 - 0
sample/src/main/java/com/drake/net/sample/ui/fragment/converter/MoshiConvertFragment.kt

@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2018 Drake, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.drake.net.sample.ui.fragment.converter
+
+import android.os.Bundle
+import android.view.View
+import com.drake.net.Get
+import com.drake.net.sample.R
+import com.drake.net.sample.convert.MoshiConvert
+import com.drake.net.sample.model.Model
+import com.drake.net.utils.scopeNetLife
+import kotlinx.android.synthetic.main.fragment_custom_convert.*
+
+
+class MoshiConvertFragment : BaseConvertFragment(R.layout.fragment_custom_convert) {
+
+    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
+        tv_convert_tip.text = """
+            1. Square出品的JSON解析库
+            2. 支持Kotlin构造默认值
+            3. 具备注解和反射两种使用方式
+            4. 非可选类型反序列化时赋值Null会抛出异常
+            5, 不支持动态解析
+        """.trimIndent()
+
+        scopeNetLife {
+            tv_fragment.text = Get<Model>("api") {
+                converter = MoshiConvert() // 单例转换器, 此时会忽略全局转换器
+            }.await().data.request_method
+        }
+    }
+}

+ 51 - 0
sample/src/main/java/com/drake/net/sample/ui/fragment/converter/SerializationConvertFragment.kt

@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2018 Drake, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.drake.net.sample.ui.fragment.converter
+
+import android.os.Bundle
+import android.view.View
+import com.drake.net.Get
+import com.drake.net.sample.R
+import com.drake.net.sample.convert.SerializationConvert
+import com.drake.net.sample.model.UserModel
+import com.drake.net.utils.scopeNetLife
+import kotlinx.android.synthetic.main.fragment_custom_convert.*
+
+
+class SerializationConvertFragment : BaseConvertFragment(R.layout.fragment_custom_convert) {
+
+    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
+        tv_convert_tip.text = """
+            1. kotlin官方出品, 推荐使用 
+            2. kotlinx.serialization 是Kotlin上是最完美的序列化工具 
+            3. 相对其他解析库他解决泛型擦除机制, 支持任何泛型, 可直接返回Map/List/Pair...
+            4. 多配置选项
+            5. 支持动态解析
+            6. 支持ProtoBuf/CBOR/JSON等数据
+        """.trimIndent()
+
+        scopeNetLife {
+            val userList = Get<List<UserModel>>("list-data") {
+                // 该转换器直接解析JSON中的data字段, 而非返回的整个JSON字符串
+                converter = SerializationConvert() // 单例转换器, 此时会忽略全局转换器
+            }.await()
+
+            tv_fragment.text = userList[0].name
+        }
+    }
+
+}

+ 11 - 1
sample/src/main/res/layout/fragment_custom_convert.xml

@@ -18,7 +18,17 @@
     xmlns:tools="http://schemas.android.com/tools"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
-    tools:context=".ui.fragment.CustomConvertFragment">
+    tools:context=".ui.fragment.converter.GsonConvertFragment">
+
+    <TextView
+        android:id="@+id/tv_convert_tip"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:gravity="center_vertical"
+        android:minHeight="50dp"
+        android:paddingHorizontal="20dp"
+        android:textSize="12dp"
+        tools:text="推荐, kotlinx.serialization支持任何泛型, 可直接返回Map/List/Pair..." />
 
     <TextView
         android:id="@+id/tv_fragment"

+ 15 - 0
sample/src/main/res/menu/menu_converter.xml

@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="utf-8"?>
+<menu xmlns:android="http://schemas.android.com/apk/res/android">
+    <item
+        android:id="@+id/serializationConvertFragment"
+        android:title="SerializationConverter(★★★★★)" />
+    <item
+        android:id="@+id/gsonConvertFragment"
+        android:title="GsonConverter(★★★)" />
+    <item
+        android:id="@+id/fastJsonConvertFragment"
+        android:title="FastJsonConverter(★★★)" />
+    <item
+        android:id="@+id/moshiConvertFragment"
+        android:title="MoshiConverter(★★)" />
+</menu>

+ 1 - 1
sample/src/main/res/menu/menu_main.xml

@@ -44,7 +44,7 @@
         android:icon="@drawable/ic_scope"
         android:title="协程作用域" />
     <item
-        android:id="@+id/custom_convert"
+        android:id="@+id/nav_converter"
         android:icon="@drawable/ic_convert"
         android:title="自定义转换器" />
     <item

+ 25 - 0
sample/src/main/res/navigation/nav_converter.xml

@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<navigation xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    xmlns:tools="http://schemas.android.com/tools"
+    android:id="@+id/nav_converter"
+    app:startDestination="@id/serializationConvertFragment">
+
+    <fragment
+        android:id="@+id/serializationConvertFragment"
+        android:name="com.drake.net.sample.ui.fragment.converter.SerializationConvertFragment"
+        android:label="Serialization" />
+    <fragment
+        android:id="@+id/gsonConvertFragment"
+        android:name="com.drake.net.sample.ui.fragment.converter.GsonConvertFragment"
+        android:label="Gson"
+        tools:layout="@layout/fragment_custom_convert" />
+    <fragment
+        android:id="@+id/fastJsonConvertFragment"
+        android:name="com.drake.net.sample.ui.fragment.converter.FastJsonConvertFragment"
+        android:label="FastJson" />
+    <fragment
+        android:id="@+id/moshiConvertFragment"
+        android:name="com.drake.net.sample.ui.fragment.converter.MoshiConvertFragment"
+        android:label="Moshi" />
+</navigation>

+ 1 - 5
sample/src/main/res/navigation/nav_main.xml

@@ -36,11 +36,6 @@
         android:name="com.drake.net.sample.ui.fragment.CoroutineScopeFragment"
         android:label="协程作用域"
         tools:layout="@layout/fragment_coroutine_scope" />
-    <fragment
-        android:id="@+id/custom_convert"
-        android:name="com.drake.net.sample.ui.fragment.CustomConvertFragment"
-        android:label="自定义转换器"
-        tools:layout="@layout/fragment_custom_convert" />
     <fragment
         android:id="@+id/error_handler"
         android:name="com.drake.net.sample.ui.fragment.ErrorHandlerFragment"
@@ -140,5 +135,6 @@
         android:id="@+id/view_model"
         android:name="com.drake.net.sample.ui.fragment.ViewModelRequestFragment"
         android:label="ViewModel" />
+    <include app:graph="@navigation/nav_converter" />
 
 </navigation>