Android Retrofit2泛型方法

cbeh67ev  于 2023-10-14  发布在  Android
关注(0)|答案(2)|浏览(142)

我使用Retrofit2连接到服务器,

为了简化请求方法的数量,我使用泛型。但问题是,改造不接受通用的方法。我把示例代码放在下面。有人知道解决办法吗?

照片1):

APIInterface

import io.reactivex.Observable
import okhttp3.RequestBody
import retrofit2.http.Body
import retrofit2.http.GET
import retrofit2.http.POST
import retrofit2.http.Path

interface APIInterface {

   @POST("{url}") fun <T> post(
      @Path("url") url: String,
      @Body body: RequestBody
   ): Observable<T>

   @GET("{url}") fun <T> get(
      @Path("url") url: String
   ): Observable<T>
}

照片二:

APIService

import io.reactivex.Observable
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.schedulers.Schedulers
import okhttp3.RequestBody
import java.io.Serializable

class APIService constructor(private val mApi: APIInterface) {

   fun <T: Serializable> post(url: String, body: RequestBody): Observable<T>{
      val observable = mApi.post<T>(url, body)
      observable.subscribeOn(Schedulers.io())
         .observeOn(AndroidSchedulers.mainThread())
      return observable
   }

   fun <T: Serializable> get(url: String): Observable<T> {
      val observable = mApi.get<T>(url)
      observable.subscribeOn(Schedulers.io())
         .observeOn(AndroidSchedulers.mainThread())
      return observable
   }
}

照片三:

call in controller

mAPIService.post<SignUpModel>(URL_SIGN_UP, body)
        .subscribe(object : APIObserver<SignUpModel> {
            override fun onNext(it: SignUpModel) {
    .
    .
    .

照片四:

crash :(

W: java.lang.IllegalArgumentException: Method return type must not include a type variable or wildcard: io.reactivex.Observable<T>
W: for method APIInterface.post
    .
    .
    .
atmip9wb

atmip9wb1#

类型信息需要在运行时完全已知,以便实现非结构化。
您不能这样做,类型信息需要完全静态,而不是泛型,否则翻新无法正确生成服务。看看here

vhmi4jdf

vhmi4jdf2#

只需添加一些公共类,通过此代码片段,您就可以轻松调用任何API

val repository = Repository(UseCase<YourModel>())

        CoroutineScope(Dispatchers.Main).launch {
            RetrofitClient.apiEndpoint?.getXyz(
                YourModel(value)
            )?.let {
                repository.fetchData(
                    it
                ) { yourModel, error ->
                    if (error != null) {
                        // Handle error
                        Log.d("CheckingResponse", "$error")
                    } else {
                        // ..success
                    }
                  }
                }
        }

客户端

object RetrofitClient {
    private const val BASE_URL = "https://xyz/"
    private var client = OkHttpClient.Builder() // add our curl logger here
        .addInterceptor(CurlLoggerInterceptor()) // curl logger to get curl when any api hits (You need to add dependency to use this)
    private val retrofit: Retrofit = Retrofit.Builder()
        .baseUrl(BASE_URL)
        .addConverterFactory(GsonConverterFactory.create())
        .client(client.build())
        .build()

    val apiEndpoint: ApiEndpoint? = retrofit.create(ApiEndpoint::class.java)

}

用例

class UseCase<T> {
    fun fetchData(endpoint: Call<ApiResponse<T>>, callback: (T?, String?) -> Unit) {
        endpoint.enqueue(object : Callback<ApiResponse<T>> {
            override fun onResponse(call: Call<ApiResponse<T>>, response: Response<ApiResponse<T>>) {
                if (response.isSuccessful) {
                    val responseData = response.body()?.data
                    callback(responseData, null)
                } else {
                    Log.d("CheckingResponse", "fetchData: ${response.message()}")
                    callback(null, "Error: ${response.message()}")
                }
            }

            override fun onFailure(call: Call<ApiResponse<T>>, t: Throwable) {
                callback(null, "Network error: ${t.localizedMessage}")
            }
        })
    }
}

查看所有普通类。https://github.com/Mohammad-Taqi/Generic-Retrofit-Implementation

相关问题