使用 Kotlin 进行 RxJava 和改造
Posted
技术标签:
【中文标题】使用 Kotlin 进行 RxJava 和改造【英文标题】:RxJava and Retrofit using Kotlin 【发布时间】:2018-05-03 17:00:26 【问题描述】:如何在 Kotlin 中使用 RxJava 和 Retrofit 创建用于 api 调用的泛型类?
我的 JAVA 实现是 ::
首先添加 Gradle 依赖项:(如果可用,更新到最新版本)
//用于改造
实现'com.squareup.retrofit2:retrofit:2.3.0'
实现'com.squareup.retrofit2:converter-gson:2.3.0'
//用于拦截器 实现 'com.squareup.okhttp3:logging-interceptor:3.9.0'
//对于 BuildType : (如果你想要各种环境)
构建类型 调试 buildConfigField "String", "SERVER_URL", '"DEV_URL"' 可调试真 发布 buildConfigField "String", "SERVER_URL", '"LIVE_URL"' 缩小启用假
//如果设置了环境使用设置环境定义BASE_URL:
字符串 BASE_URL = BuildConfig.SERVER_URL + "url";
================================================ ======== 为 Retrofit Builder 创建一个名为 RestClient 的类:
public class RestClient
private static RestClient instance;
private ApiConstant apiInterface;
private OkHttpClient.Builder okHttpClientBuilder;
public RestClient()
instance = this;
okHttpClientBuilder = new OkHttpClient.Builder();
okHttpClientBuilder.connectTimeout(60, TimeUnit.SECONDS);
okHttpClientBuilder.writeTimeout(60, TimeUnit.SECONDS);
okHttpClientBuilder.readTimeout(60, TimeUnit.SECONDS);
//for logs of api response in debug mode
if (BuildConfig.DEBUG)
final HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
okHttpClientBuilder.addInterceptor(interceptor);
public static RestClient getInstance()
return instance;
public ApiConstant getApiInterface()
final Retrofit.Builder retrofitBuilder = new Retrofit.Builder();
retrofitBuilder.baseUrl(ApiConstant.BASE_URL);
retrofitBuilder.client(okHttpClientBuilder.build());
retrofitBuilder.addConverterFactory(GsonConverterFactory.create());
Retrofit retrofit = retrofitBuilder.build();
apiInterface = retrofit.create(ApiConstant.class);
return apiInterface;
================================================ ======== ApiInterface : (api调用的接口)
public interface ApiInterface
@POST("Urls Params")
Call<ModelClass> postValidateToken(@Body JSONObject body);
================================================ ======== 创建名为 RetrofitCallback 的通用类,它处理 Api 响应并引发基本错误并向用户显示 Toast 消息:
public abstract class RetrofitCallback<T> implements Callback<T>
private ProgressDialog progressDialog;
private Context context;
private boolean validateResponse = true;
public RetrofitCallback(Context c)
context = c;
public RetrofitCallback(Context c, ProgressDialog dialog)
progressDialog = dialog;
context = c;
public RetrofitCallback(Context context, ProgressDialog progressDialog, boolean validateResponse)
this.progressDialog = progressDialog;
this.context = context;
this.validateResponse = validateResponse;
public RetrofitCallback(Context context, boolean validateResponse)
this.context = context;
this.validateResponse = validateResponse;
public abstract void onSuccess(T arg0);
@Override
public void onResponse(Call<T> call, Response<T> response)
if (!(((Activity) context).isFinishing()) && progressDialog != null && progressDialog.isShowing())
if (progressDialog != null && progressDialog.isShowing())
progressDialog.dismiss();
if (response.isSuccessful() && response.code() == 200)
onSuccess(response.body());
else
Toast.makeText(context, context.getString(R.string.something_wrong), Toast.LENGTH_SHORT).show();
@Override
public void onFailure(Call<T> call, Throwable error)
if (!validateResponse)
return;
String errorMsg;
error.printStackTrace();
if (error instanceof SocketTimeoutException)
errorMsg = context.getString(R.string.connection_timeout);
else if (error instanceof UnknownHostException)
errorMsg = context.getString(R.string.nointernet);
else if (error instanceof ConnectException)
errorMsg = context.getString(R.string.server_not_responding);
else if (error instanceof JSONException || error instanceof JsonSyntaxException)
errorMsg = context.getString(R.string.parse_error);
else if (error instanceof IOException)
errorMsg = error.getMessage();
else
errorMsg = context.getString(R.string.something_wrong);
if (progressDialog != null && progressDialog.isShowing())
if (progressDialog != null && progressDialog.isShowing())
progressDialog.dismiss();
Toast.makeText(context, errorMsg, Toast.LENGTH_SHORT).show();
================================================ ======== 字符串:(字符串.xml)
出了点问题。请稍后再试。 没有可用的互联网连接。请稍后再试。 服务器没有响应。请稍后再试。 连接超时 无法解析来自服务器的响应
================================================ ======== 实现(如何在Activity或Fragment中调用):
Call<User> userLoginCall = RestClient.getInstance().getApiInterface().LoginURL(Util.currentLanguage,
Util.getLoginURL(getActivity(), email, LOGIN_GOOGLE, accID));
userLoginCall.enqueue(new RetrofitCallback<User>(getActivity(), DialogUtils.showProgressDialog(getActivity()))
@Override
public void onSuccess(User user)
//Your Response
);
【问题讨论】:
“泛型类”是什么意思,到目前为止您尝试过什么? 我是 kotlin 的新手,所以我想通过创建一个直接处理错误并直接给出 onSuccess 的通用类来简化我的 api 调用使用 RxJava... github.com/ApploverSoftware/android_architecture/tree/master/… github.com/ApploverSoftware/android_architecture/blob/master/… 我现在没有时间解释它(如果你需要的话,可能稍后再解释)。我的架构旨在使用 zip 或 merge 等 rx 方法更轻松地优化代码。 您可以使用这个适配器库,以便您可以将 RxJava 与 Retrofit 一起使用:github.com/square/retrofit/tree/master/retrofit-adapters/…retrofitBuilder.addCallAdapterFactory(RxJava2CallAdapterFactory.createAsync())
【参考方案1】:
我使用一个 ServiceGenerator 类,以防我需要使用多个 Retrofit Service 接口。
object ServiceGenerator
const val APP_CODE = "APP_CODE"
private val interceptor = HttpLoggingInterceptor()
.setLevel(HttpLoggingInterceptor.Level.BODY)
private val certificatePinner = CertificatePinner.Builder()
.add(BuildConfig.HOSTNAME, BuildConfig.SHA1_HASH1)
.add(BuildConfig.HOSTNAME, BuildConfig.SHA1_HASH2)
.add(BuildConfig.HOSTNAME, BuildConfig.SHA1_HASH3)
.add(BuildConfig.HOSTNAME, BuildConfig.SHA1_HASH4)
.build()
private val httpClient = OkHttpClient.Builder()
.readTimeout(1, TimeUnit.MINUTES)
.connectTimeout(1, TimeUnit.MINUTES)
.addInterceptor(interceptor)
private val builder = Retrofit.Builder()
.baseUrl(BuildConfig.URL_ENDPOINT)
.addCallAdapterFactory(
RxJava2CallAdapterFactory.createWithScheduler(Schedulers.io())
)
.addConverterFactory(GsonConverterFactory.create())
private var requestInterceptor: AppEventosRequestInterceptor? = null
fun <S> createService(context: Context, serviceClass: Class<S>): S
if (BuildConfig.FLAVOR.equals("production"))
httpClient.certificatePinner(certificatePinner)
if (!httpClient.interceptors().contains(requestInterceptor))
requestInterceptor = AppEventosRequestInterceptor(context)
httpClient.addInterceptor(requestInterceptor!!)
builder.client(httpClient.build())
val retrofit = builder.build()
return retrofit.create(serviceClass)
在我的例子中,我让我的服务能够返回一个 Flowable 响应,以便我可以观察它。
@GET("schedule")
fun getSchedules(
@Header("If-None-Match") etag: String
): Flowable<Response<ResponseBody>>
然后,当我想进行 http 调用时,我首先初始化我的 ServiceRx 类
private var mService: AppEventosServiceRx = ServiceGenerator.createService<AppEventosServiceRx>(applicationContext, AppEventosServiceRx::class.java)
然后提出我的要求
mService.getSchedules(mEtagManager.getEtag(EtagManager.ETAG_SCHEDULES))
.observeOn(AndroidSchedulers.mainThread())
.subscribe(
response ->
if (response.code() != HttpURLConnection.HTTP_NOT_MODIFIED)
if (response.body() != null)
// Do your useful stuff here...
else
// Check if not modified or any other HTTP Error
,
throwable ->
// Log your connectivity problems ...
)
这样,您的服务接口将为您提供一个观察者,服务生成器将使其对每个调用都通用,您可以观察它并处理响应。
希望对你有帮助!
【讨论】:
以上是关于使用 Kotlin 进行 RxJava 和改造的主要内容,如果未能解决你的问题,请参考以下文章