在Kotlin中使用Retrofit

时间:2018-03-22 06:05:45

标签: kotlin gson retrofit

我正在尝试使用kotlin中的改造来打击api

这是我的DoinBackGround方法

private fun doinBackground() {

    Utility.printMessage("in do in  background.....")
    try {
        val hdr = HashMap<String, String>()
        hdr.put("x-csrf-token", Utility.getToken(this.context!!))

        val apiInterface = ApiCallRetrofit.getClient(this.mCrypt!!)!!.create(ApiInterface::class.java)



        if (what.equals(0)) {
            val body = RequestBody.create(MediaType.parse("application/json; charset=utf-8"), getQuery(para))
            print("header...")
            call = apiInterface.hitApi(url, hdr, body)


        } else if (what.equals(1)) {

            val imgPart = ArrayList<MultipartBody.Part>()
            if (files != null) {
                if (files.size > 0) {
                    for (i in files.indices) {
                        imgPart.add(preparePart("image/*", "document_file[" + files.get(i).key + "]", files.get(i).file))
                    }
                }
                call = apiInterface.hitApiImage(url, hdr, getMap(para), imgPart)

            }



            call?.enqueue(object : Callback<StandardReposnse> {
                override fun onResponse(call: Call<StandardReposnse>, response: Response<StandardReposnse>) {
                    try {

                        Utility.printMessage("messege...." + response.body().message)
                        val resp = Gson().toJson(response.body())
                        Utility.printMessage("Response :$resp")
                        Utility.longLogPrint(response.body().data, "Full response : ")
                        Utility.printMessage("Error : " + Gson().toJson(response.errorBody()))
                        onPostExecute(Parseresponce(response.body()))
                    } catch (e: Exception) {
                        Parseresponce(null)

                        e.printStackTrace()
                    }

                }

                override fun onFailure(call: Call<StandardReposnse>, t: Throwable) {
                    t.printStackTrace()
                    if (progressDialog != null) {
                        progressDialog?.dismiss()
                    }
                    Parseresponce(null)
                }
            })
        }

    } catch (e: Exception) {
        e.printStackTrace()
    }


}

这是我定义所有POST方法的界面

@POST
abstract fun hitApi(@Url api: String, @HeaderMap header: Map<String, Any>, @Body body: RequestBody): Call<StandardReposnse>


@POST
fun hitApiNoHeader(@Url api: String, @Body requestBody: RequestBody): Call<StandardReposnse>

@POST
fun test(@Url api: String, @HeaderMap headerMap: Map<String, String>, @Body requestBody: RequestBody): Call<JSONObject>

@Multipart
@POST
fun hitApiImage(@Url api: String, @HeaderMap headerMap: Map<String, String>, @PartMap bodyMap: Map<String, RequestBody>, @Part images: List<MultipartBody.Part>): Call<StandardReposnse>

每当我试图击中Api时,我都会遇到以下异常:

java.lang.IllegalArgumentException: Parameter type must not include a type variable or wildcard: java.util.Map<java.lang.String, ?> (parameter #2)
for method ApiInterface.hitApi
at retrofit2.ServiceMethod$Builder.methodError(ServiceMethod.java:720)
at retrofit2.ServiceMethod$Builder.methodError(ServiceMethod.java:711)
at retrofit2.ServiceMethod$Builder.parameterError(ServiceMethod.java:729)
at retrofit2.ServiceMethod$Builder.build(ServiceMethod.java:193)
at retrofit2.Retrofit.loadServiceMethod(Retrofit.java:166)

这是doinbackground方法中发生异常的行

call = apiInterface.hitApi(url, hdr, body)

我在RequestBody之前尝试了@JvmSuppressWildcards,但它没有用,有人能说明这里的实际问题是什么,加上没有什么东西在日志中打印虽然我用过print()函数应该用LOGD吗?

3 个答案:

答案 0 :(得分:0)

您使用过:

ClaimsPrincipal principal = Request.GetRequestContext().Principal as ClaimsPrincipal;

var Name = ClaimsPrincipal.Current.Identity.Name;

例外是:

@POST
abstract fun hitApi(@Url api: String, @HeaderMap header: Map<String, Any>, @Body body: RequestBody): Call<StandardReposnse>

你的hitApi#2 param实际上使用了通配符:

Parameter type must not include a type variable or wildcard: java.util.Map<java.lang.String, ?> (parameter #2)

尝试指定参数(只需将Any更改为String)。无论如何,你可能不会在请求标题中放置任何对象而不是String。

答案 1 :(得分:0)

以下面提到的方式调用它。

  val callWeather = NetworkUtils.getApiInterface().getWeatherResponse("03a7949903004a0bb2590633181104", "1.909,45.909", 7)

            callWeather.enqueue(object : Callback<APIXUResponse> {
                override fun onResponse(call: Call<APIXUResponse>, response: Response<APIXUResponse>) {
                    var api :APIXUResponse? = response.body()
                }

                override fun onFailure(call: Call<APIXUResponse>, t: Throwable) {

                }
            })

答案 2 :(得分:0)

这里我有一个完整的例子。

这种依赖性增加了作用

implementation 'com.squareup.retrofit2:retrofit:2.5.0'
annotationProcessor 'com.squareup.retrofit2:retrofit:2.5.0'
implementation 'com.squareup.retrofit2:converter-gson:2.4.0'

现在在这里创建 ApiClient.kt 文件

object ApiClient {

val BASE_URL = "http://yourwebsite/services/"
private var retrofit: Retrofit? = null

val client: Retrofit
    get() {
        if (retrofit == null) {
            retrofit = Retrofit.Builder()
                .baseUrl(BASE_URL)
                .addConverterFactory(GsonConverterFactory.create())
                .build()
        }
        return retrofit!!
    }

}

现在创建 APIInterface.kt

@FormUrlEncoded
@POST("users/login")
fun POST_LOGIN(
        @Field("imei_number") imei_number: String,
        @Field("device_token") device_token: String,
        @Field("mobile") mobile: String,
        @Field("password") password: String
): Call<LoginResponse>

@GET("general/init-data")
fun GENERAL_MODULE(
        @Header("Authorization") auth_key: String
): Call<InitResponse>

@GET("event-gallery/list")
fun GET_Event_GALLERY(
        @Header("Authorization") auth_key: String
): Call<EventListResponse>

@GET("event-gallery/photo-list")
fun GET_Event_GALLERY_PHOTO(
        @Header("Authorization") auth_key: String,
        @Query("id") id: Int
): Call<EventGallerListResponse>

如果有任何用于令牌的标头,则使用@Header,并且在调用@GET时,使用@Query和@Post时使用@Fields

现在的响应文件

data class EventListResponse(
    @SerializedName("success")
    var success: Boolean,
    @SerializedName("data")
    var data: EventgalleryModel?,
    @SerializedName("server_error"),
    @SerializedName("eventgallery")
    var eventgallery: ArrayList<EventListData>
    var server_error: Boolean,
    @SerializedName("message")
    var message: String

然后创建Response的Model类

现在需要活动代码

private fun loadData() {
    card_progress.visibility = View.VISIBLE
    val apiService = ApiClient.client.create(ApiInterface::class.java)
    val call =
        apiService.GET_FEE_INSTALMENT_LIST(PreferenceManager.getAuthKey(this@FeesInstalmentActivity)!!)
    call.enqueue(object : Callback<FeeInstalmentListResponse> {
        override fun onResponse(
            call: Call<FeeInstalmentListResponse>,
            response: Response<FeeInstalmentListResponse>
        ) {
            card_progress.visibility = View.GONE
            val data = response.body()!!.data
            if (response.code() == 200 && data != null) {
                if (response.body()!!.server_error) {
                    txt_no_data_fee.visibility = View.VISIBLE
                    txt_no_data_fee.text = response.body()!!.message
                } else {
                    Log.e("data", data.toString())
                    if (data != null && data.feesinstalment.isEmpty()) {
                        txt_no_data_fee.visibility = View.VISIBLE
                    } else {
                        txt_no_data_fee.visibility = View.GONE
                        adapter!!.setItem(data.feesinstalment)
                    }
                }
            } else if (response.code() == 401) {
                PreferenceManager.removePref(this@FeesInstalmentActivity)
                startActivity(
                    Intent(this@FeesInstalmentActivity, LoginActivity::class.java)
                        .addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_CLEAR_TASK or Intent.FLAG_ACTIVITY_NEW_TASK)
                )
                finish()
            } else {
                Toast.makeText(
                    this@FeesInstalmentActivity,
                    R.string.somethingWrong,
                    Toast.LENGTH_SHORT
                ).show()
            }


        }

        override fun onFailure(call: Call<FeeInstalmentListResponse>, t: Throwable) {
            card_progress.visibility = View.GONE
            Log.e("onFailure", t.message)
            txt_no_data_fee.visibility = View.VISIBLE
        }
    })
}

适配器

class FeeInstalmentAdapter(
    private val context: Context,
    private var items: ArrayList<FeeInstalmentListData>

):RecyclerView.Adapter(){

override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
    return ViewHolder(LayoutInflater.from(context).inflate(R.layout.row_fees_instalment_item, parent, false))
}

@SuppressLint("SetTextI18n")
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
    holder.due_date.text = DateHelper.parseData(items[position].due_date!!, "yyyy-MM-dd", "dd MMM yyyy")
    holder.instalment_title.text = items[position].instalment_title
    if (items[position].paid_date == null) {
        holder.paid_text.visibility = View.GONE
        holder.paid_date.text = context.resources.getString(R.string.UnPaid)
        holder.paid_date.setTextColor(Color.parseColor("#DC143C"))
    } else {
        holder.paid_date.text = DateHelper.parseData(items[position].due_date!!, "yyyy-MM-dd", "dd MMM yyyy")
        holder.paid_date.setTextColor(Color.parseColor("#58A259"))
    }
    //holder.paid_date.text = items[position].paid_date
    holder.amount.text = "Rs. " + items[position].amount
    holder.amount.setTextColor(Color.parseColor("#ED7136"))

}


override fun getItemCount(): Int {
    return items.size
}

override fun getItemId(position: Int): Long {
    return position.toLong()
}

override fun getItemViewType(position: Int): Int {
    return position
}

fun setItem(holidays: ArrayList<FeeInstalmentListData>) {
    items = holidays
    notifyDataSetChanged()
}


class ViewHolder(view: View) : RecyclerView.ViewHolder(view) {
    val due_date = view.due_date
    val instalment_title = view.instalment_title
    val paid_date = view.paid_date
    val amount = view.amount
    val paid_text = view.paidText
}

}