Retrofit网络请求
步骤:
1、设置路由地址
Retrofit retrofit = new Retrofit
.Builder()
.baseUrl(ApiUtils.BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.build();
2、书写请求接口
public interface UserMgrService {
/**
* GET 用 Query
*/
@GET("login")
Call<UserBean> login(@Query("username") String username, @Query("password") String password);
}
3、实现请求接口
UserMgrService service = retrofit.create(UserMgrService.class);
4、获取call对象
Call<UserBean> call = service.login( mAccountEdit.getText().toString(), mPasswordEdit.getText().toString());
5、发送请求
5.1 同步请求
Response<UserBean> response = call.execute();
Log.d("123123", "msg--" + response.body().getUser_head_img());
5.2 异步请求
//回调
call.enqueue(new Callback<UserBean>() {
@Override
public void onResponse(Call<UserBean> call, Response<UserBean> response) {
Log.d("123123", "msg--" + response.body().getUser_head_img());
}
@Override
public void onFailure(Call<UserBean> call, Throwable t) {
// 失败时做处理
}
});
Retrofit+liveData
Retrofit 和 LiveData 结合的⼀种实现⽅法
- 构建 Retrofit 对象时,添加⼀个转换适配器⼯⼚ CallAdapterFactory
- CallAdapterFactory ⽣产的适配器 CallAdapter 需要重写两个⽅法
*responseType()
*adapt()
responseType()⽤于返回从GSON数据到JAVA对象的类型
adapt()该⽅法⽤于将 Retrofit 请求返回时的 Call对象转换为需要的类,这⾥为我们⾃定义的 LiveData对象,为了后续监听⽹络回调,这⾥CallAdapterFactory 构建 CallAdapter 时需要传递当前 Call 实例 - 我们⾃定义的 LiveData 对象需要重写
*onActive()
onActive()该⽅法在 LiveData 实例的 observer 由 0变1 时会调⽤,我们传递进来的 Call 在这⾥使⽤。
由于⽹络线程在后台运⾏,此时应该对 Call 实例 enqueue ⼀个 Callback,Callback 重写的⽅法中对 LiveData 进⾏onResponse()调用postValue<T>()
这样我们的LiveData在有observer后就能及时收到请求的回调并进⾏更新
具体实现
1、实现CallAdapterFactory
class LiveDataCallAdapterFactory : CallAdapter.Factory() {
override fun get(
returnType: Type,
annotations: Array<out Annotation>,
retrofit: Retrofit
): CallAdapter<*, *>? {
if (getRawType(returnType) != LiveData::class.java) return null
//获取第一个泛型类型
val observableType = getParameterUpperBound(0, returnType as ParameterizedType)
return LiveDataCallAdapter<Any>(observableType)
}
}
2、实现CallAdapter
class LiveDataCallAdapter<T>(private val responseType: Type):CallAdapter<T,LiveData<T>>{
override fun responseType(): Type {
return responseType
}
override fun adapt(call: Call<T>): LiveData<T> {
return object : LiveData<T>() {
private val started = AtomicBoolean(false)
override fun onActive() {
super.onActive()
if (started.compareAndSet(false, true)) {//确保执行一次
call.enqueue(object : Callback<T> {
override fun onFailure(call: Call<T>, t: Throwable) {
postValue(null)
}
override fun onResponse(call: Call<T>, response: Response<T>) {
postValue(response.body())
}
})
}
}
}
}
}
3、将LiveDataCallAdapterFactory和retrofit 关联
private void initRetrofit() {
HttpLoggingInterceptor loggingInterceptor = new HttpLoggingInterceptor();
//1、初始话OKhttp
OkHttpClient client = new OkHttpClient.Builder()
.connectTimeout(60, TimeUnit.SECONDS) //设置请求超市时间
.readTimeout(60,TimeUnit.SECONDS) //设置读取超时时间
.writeTimeout(60,TimeUnit.SECONDS) //设置写入超时时间
.retryOnConnectionFailure(true) //设置出现错误时重连
.addInterceptor(new HeadIntercept())
.addInterceptor(loggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY))
.build();
//2、初始化retrofitl
retrofit = new Retrofit.Builder()
.client(client)
.baseUrl(Constants.BASE_URL)
.addConverterFactory(GsonConverterFactory.create(new Gson()))
.addCallAdapterFactory(new LiveDataCallAdapterFactory())
.build();
}
4、网络请求接口
public interface UserMgrServiceLiveData {
//post 传body
@POST("api/medical/applogin")
LiveData<UserNewsBean> login(@Body UserBean body);
}
5、调用
UserBean userBean= new UserBean();
userBean.setIdcard(userName);
userBean.setPassword(pwd);
apiService.login(userBean).observe((LifecycleOwner) context, new Observer<UserNewsBean>() {
@Override
public void onChanged(UserNewsBean userNewsBeanApiResponse) {
Log.e( "onChanged: ",userNewsBeanApiResponse.toString());
}
});
完成上边就可以使用liveData+retrofit进行网络请求了
但是,这并不是它的最终形态。
如果我们后台返回的接口是统一的格式:
例如是:
{
data:[],//或者{}
errorCode:0,
errorMsg:""
}
那么我们可以定义已个统一的处理类
class ApiResponse<T> (
var data: T?,
var errorCode: Int,
var errorMsg:String
)
然后在我们的CallAdapterFactory类中做响应的调整如下即添加
val rawType = getRawType(observableType)
if (rawType != ApiResponse::class.java) {
throw IllegalArgumentException(“type must be ApiResponse”)
}
if (observableType !is ParameterizedType) {
throw IllegalArgumentException(“resource must be parameterized”)
}
这些代码
class LiveDataCallAdapterFactory : CallAdapter.Factory() {
override fun get(
returnType: Type,
annotations: Array<out Annotation>,
retrofit: Retrofit
): CallAdapter<*, *>? {
if (getRawType(returnType) != LiveData::class.java) return null
//获取第一个泛型类型
val observableType = getParameterUpperBound(0, returnType as ParameterizedType)
val rawType = getRawType(observableType)
if (rawType != ApiResponse::class.java) {
throw IllegalArgumentException("type must be ApiResponse")
}
if (observableType !is ParameterizedType) {
throw IllegalArgumentException("resource must be parameterized")
}
return LiveDataCallAdapter<Any>(observableType)
}
}
最后调整我们的请求接口类如下
public interface UserMgrServiceLiveData {
//post 传body
@POST("api/medical/applogin")
LiveData<ApiResponse<UserNewsBean>> login(@Body UserBean body);
}
调用方式不变