Почему мой блок инициализации в моем классе не срабатывает при использовании модернизации? - PullRequest
0 голосов
/ 31 января 2019

поэтому с сервера я получу JSON следующим образом:

{
    "success": "1",
    "data": [
        {
            "id": 1,
            "title": "1",
            "url": "5",
            "image": "resources/assets/images/banner_images/1548316546.mitra lakuin.png",
            "type": "category"
        },
        {
            "id": 2,
            "title": "2",
            "url": "5",
            "image": "resources/assets/images/banner_images/1548316605.mobile banner_-02 (1).png",
            "type": "category"
        },
        {
            "id": 4,
            "title": "4",
            "url": "5",
            "image": "resources/assets/images/banner_images/1547010221.gratis ongkir.png",
            "type": "category"
        },
        {
            "id": 5,
            "title": "Customer",
            "url": "5",
            "image": "resources/assets/images/banner_images/1548316659.customer service.png",
            "type": "category"
        }
    ],
    "message": "Banners are returned successfull."
}

, и я создаю 2 класса для преобразования этого JSON в Banner Object.

// 1.
class BannerData(val message : String, val success : String, val data : List<Banner>) {}

// 2.

class Banner(id: Int, imageURL: String) {

    @SerializedName("image")
    var imageURL : String
    val id : Int

    init {
        Log.i("testX","triggered")

        this.id = id

        // The code below is used to add percent encoding to URL from server

        val unformattedFullPath = "${Endpoint.lakuin}/$imageURL"
        val formattedFullPath = URLConverterService.addingPercentEncoding(unformattedFullPath)
        this.imageURL = formattedFullPath

    }

}

интерфейс для модернизациикак это:

    @GET("/app/getbanners")
    fun getBanners(): Call<BannerData>

, а построитель интерфейса выглядит так:

object RetrofitHandler {

    private val loggingInterceptor = HttpLoggingInterceptor().setLevel(HttpLoggingInterceptor.Level.BODY)

    private val okHttpClient = OkHttpClient.Builder()
        .callTimeout(7,TimeUnit.SECONDS)
        .addInterceptor(loggingInterceptor)
        .build()

    private var retrofit = Retrofit.Builder()
        .baseUrl(Endpoint.lakuin) // default is set to lakuinAPI
        .addConverterFactory(GsonConverterFactory.create())
        .client(okHttpClient)
        .build()


    fun <T> getInstance(APIType: Class<T>) : T {
        // baseURL should be change later, if there is more than one API, ex: GoogleMapAPI, LakuinAPI etc
        return retrofit.create(APIType)
    }

}

и моя проблема .....

, как вы можете видеть из JSONвыше, URL изображения не является полным, я хочу преобразовать imageURL

из: "resources / blablabla.png"

в: "http://xxxx.com/resources/blablabla.png"

иЯ пытаюсь преобразовать его в блоке init в классе Banner.

, но ..... кажется, что блок init в классе Banner никогда не запускается, я пытаюсь зарегистрировать его, но яне могу найти в logcat, что Log.i("testX","triggered") никогда не показывается в logcat

Я действительно могу создать объект Banner, но imageURL точно такой же, как и в JSON, это означает, что блок init никогда не запускается enter image description here

так что здесь не так?

Ответы [ 2 ]

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

Просто оберните ваш URL в отдельный класс

data class EndPointUrl(val url: String)

Создайте класс и расширьте JsonDeserializer и JsonSerializer, которые преобразуют вашу строку в EndPointUrl и наоборот

class EndPointUrlSerializer : JsonDeserializer<EndPointUrl>, JsonSerializer<EndPointUrl> {

    @Throws(JsonParseException::class)
    override fun deserialize(
            json: JsonElement,
            type: Type,
            context: JsonDeserializationContext
    ) = EndPointUrl("${Endpoint.lakuin}/${json.asString}")

    override fun serialize(
            src: EndPointUrl,
            type: Type,
            context: JsonSerializationContext
    ) = JsonPrimitive(src.url)
}

Зарегистрируйте ваш сериализатор в объекте gson:

val gson = GsonBuilder()
                 .registerTypeAdapter(EndPointUrl::class.java, EndPointUrlSerializer())
                 .create()

Используйте этот модифицированный объект gson:

val retrofit = Retrofit.Builder()
                   .baseUrl(BASE_URL)
                   .addConverterFactory(GsonConverterFactory.create(gson))
                   .build()

Теперь вы можете поместить EndPointUrl в ваш объект ответа:

data class Banner(id: Int, imageURL: EndPointUrl)
0 голосов
/ 31 января 2019

Если вы установили модификацию для использования библиотеки Gson в качестве библиотеки для сериализации / десериализации объектов addConverterFactory(GsonConverterFactory.create(gson)), Gson по умолчанию не использует конструктор или функцию инициализации, вместо этого она instantiate an object and set its fields via reflection, поэтому я предполагаю, что ваш блок инициализации только что пропущен, возьмитевзгляните на библиотеку Gson, чтобы понять, можете ли вы настроить, чтобы не пропустить функцию init.

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