Как правильно сделать класс многоразового использования для перехвата данных ответов с помощью модернизации? - PullRequest
0 голосов
/ 23 января 2019

Я новичок в разработке для Android и пытаюсь получить данные с сервера. общая структура ответа JSON будет такой

{
    "success": "1",
    "data": [
        {
            "customers_id": 4,
            "customers_gender": "0",
            "customers_firstname": "TES IOS",
            "customers_lastname": "TES IOS",
            "customers_dob": "2018-12-27",
            "email": "TES002@email.com",
            "user_name": "TES002",
            "customers_default_address_id": 0,
            "customers_telephone
         },
    "message": "Successfully get user data from server"
}

поля «success» и «message» будут одинаковыми (всегда будет строкой). но «данные» могут отличаться для другого запроса вызова. Он может отправлять пользовательские данные, хранить данные или данные о продукте или даже массив / список продуктов.

поэтому я хочу создать общий многократно используемый класс для перехвата этого ответа JSON. класс будет таким, я установил для «data» значение Any, а затем он снова будет приведен к объекту User:

class ServerData(successStatus: Int, data: Any, message: String) {

    val isSuccessfull : Boolean
    val data : Any
    val message : String


    init {
        isSuccessfull = successStatus != 0
        this.data = data
        this.message = message
    }


}

интерфейс такой:

interface LakuinAPI {

    @FormUrlEncoded
    @POST("processlogin")
    fun performLogin(
        @Field("kode_customer") outletCode: String,
        @Field("password") password: String
    ): Call<ServerData>


}

и затем я использую его в упражнении, как показано ниже:

private fun sendLoginDataToServer(outletCode: String, password: String) {

        val call = lakuinAPI.performLogin(outletCode,password)

        call.enqueue(object: Callback<ServerData> {

            override fun onFailure(call: Call<ServerData>, t: Throwable) {
                Toast.makeText(this@LoginActivity,t.localizedMessage,Toast.LENGTH_LONG).show()
            }

            override fun onResponse(call: Call<ServerData>, response: Response<ServerData>) {

                if (!response.isSuccessful) {
                    Toast.makeText(this@LoginActivity,"Code: " + response.code(),Toast.LENGTH_LONG).show()
                    return
                }

                val lakuinServerData = response.body()
                val userList = lakuinServerData?.data as List<User> // the error in here
                val userData = userList.first() // the error in here
                println(userData)

            }

        })


    }

но я получаю сообщение об ошибке:

java.lang.ClassCastException: com.google.gson.internal.LinkedTreeMap не может быть приведен к com.ssss.lakuinkotlin.Model.User

Я даю комментарий в коде выше места ошибки. Я не знаю, почему это произошло.

Если честно, я не уверен, что это правильный способ получения пользовательских данных из общего JSON-ответа, подобного JSON выше. есть ли лучший способ?

Ответы [ 2 ]

0 голосов
/ 23 января 2019

Попробуйте заменить эту строку:

val userList = lakuinServerData?.data as List<User> 

на:

val userList = lakuinServerData?.data as new TypeToken<List<User>>(){}.getType()
0 голосов
/ 23 января 2019

Вы можете использовать дженерики для достижения этого

class Response<Data> constructor() : ResponseSimple() {
   @SerializedName(FIELD_DATA)
   var data: Data? = null
   private constructor(data: Data) : this() {
       this.data = data
   }
   companion object {
       const val FIELD_SUCCESS = "success"
       const val FIELD_ERROR = "error"
       const val FIELD_DATA = "data"
       const val FIELD_MESSAGE = "message"

       @JvmStatic
       fun <Data> create(data: Data): Response<Data> {
          return Response(data)
       }
   }
}

И ResponseSimple равно

open class ResponseSimple {

@SerializedName(Response.FIELD_ERROR)
var error: String = ""

@SerializedName(Response.FIELD_SUCCESS)
var succes: Boolean = false

@SerializedName(Response.FIELD_MESSAGE)
var message:String = ""
}

Тогда ответ API должен быть Call<Response<ServerData>>.

И околоClassCastException, вы не можете конвертировать ServerData в User, просто используя as.Вам нужно использовать Call<Response<ArrayList<User>>> или создать конвертер классов.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...