先在build.gradle中添加依赖
//网络请求
implementation 'com.squareup.retrofit2:retrofit:2.2.0'
implementation 'com.squareup.retrofit2:converter-gson:2.2.0'
implementation 'com.squareup.retrofit2:adapter-rxjava2:2.2.0'
implementation 'com.squareup.okhttp3:logging-interceptor:3.5.0'
implementation 'com.squareup.retrofit2:converter-scalars:2.0.2'
implementation 'com.google.code.gson:gson:2.8.0'
//Rxjava
//compile 'io.reactivex.rxjava2:rxjava:2.0.8'
implementation 'io.reactivex.rxjava2:rxandroid:2.0.1'
implementation 'com.android.support:multidex:1.0.1'
在清单文件中添加网络请求权限:
<uses-permission android:name="android.permission.INTERNET"/>
基类:
ResponseBean
package com.example.testcsdnproject.network;
public class ResponseBean<T> {
/**
* 成功
*/
public static final int SUCCESS = 200;
/**
* 失败
*/
public static final int ERROR = 2;
/**
* 登录信息失效
*/
public static final int LOGIN_TIME_OUT = 10000;
/**
* 请求结果状态
* {@value SUCCESS 请求成功}
* {@value ERROR 请求失败}
* {@value LOGIN_TIME_OUT 登录信息失效}
*/
private int status;
/**
* 返回消息
*/
private String message;
/**
* 数据
*/
private T data;
private int code;
public int getStatus() {
return status;
}
public void setStatus(int status) {
this.status = status;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public T getData() {
return data;
}
public void setData(T data) {
this.data = data;
}
public int getCode() {
return code;
}
public void setCode(int code) {
this.code = code;
}
}
PostJsonBody
package com.example.testcsdnproject.network;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import java.io.IOException;
import java.nio.charset.Charset;
import okhttp3.MediaType;
import okhttp3.RequestBody;
import okhttp3.internal.Util;
import okio.BufferedSink;
public class PostJsonBody extends RequestBody {
private static final MediaType JSON = MediaType.parse("application/json; charset=utf-8");
private static final Charset charset = Util.UTF_8;
private String content;
public PostJsonBody(@NonNull String content) {
this.content = content;
}
public String getContent() {
return content;
}
@Nullable
@Override
public MediaType contentType() {
return JSON;
}
@Override
public void writeTo(@NonNull BufferedSink sink) throws IOException {
byte[] bytes = content.getBytes(charset);
if (bytes == null) throw new NullPointerException("content == null");
Util.checkOffsetAndCount(bytes.length, 0, bytes.length);
sink.write(bytes, 0, bytes.length);
}
public static RequestBody create(@NonNull String content) {
return new PostJsonBody(content);
}
}
MyAPIException
package com.example.testcsdnproject.network;
public class MyAPIException extends RuntimeException{
public int errorCode;
MyAPIException(int errorCode,String message){
super();
this.errorCode = errorCode;
}
}
MyAPILoginException
package com.example.testcsdnproject.network;
/**
* 登录异常
* 描述:http数据异常类
*/
public class MyAPILoginException extends RuntimeException {
int errorCode;
MyAPILoginException(int errorCode, String message) {
super(message);
this.errorCode = errorCode;
}
}
MyConverterFactory
package com.example.testcsdnproject.network;
import android.content.Intent;
import android.util.Log;
import com.google.gson.Gson;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.IOException;
import java.lang.annotation.Annotation;
import java.lang.reflect.Type;
import okhttp3.ResponseBody;
import retrofit2.Converter;
import retrofit2.Retrofit;
public class MyConverterFactory extends Converter.Factory {
private static final int STATE_SUCCESS = 1;
private static final int STATE_FAILED = 0;
private static final int STATE_FAILED2 = 2;
private static final int STATE_LOGIN_ERROR = 401;
private Gson mGson = new Gson();
public static MyConverterFactory create() {
return new MyConverterFactory();
}
@Override
public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations, Retrofit retrofit) {
return new QlResponseConverter<>(type);
}
/**xx
* 响应解析
*/
private class QlResponseConverter<T> implements Converter<ResponseBody, T> {
private Type mType;
QlResponseConverter(Type type) {
mType = type;
}
@Override
public T convert(ResponseBody value) throws IOException {
return parser2(value);
}
/**
* 第一种解析
* test
*
* @param value
* @return
* @throws IOException
*/
private T parser(ResponseBody value) throws IOException {
String response;
try {
response = value.string();
if (mType == String.class) {
return (T) response;
} else {
JSONObject jsonObject = new JSONObject(response);
int state = jsonObject.getInt("status");
if (state == STATE_FAILED) {
String msg = jsonObject.getString("msg");
throw new MyAPIException(state, msg);
} else {
String data = jsonObject.getString("data");
return mGson.fromJson(data, mType);
}
}
} catch (JSONException e) {
throw new MyAPIException(0, "数据解析异常");
} finally {
value.close();
}
}
/**
* 第二种解析
*
* @param value
* @return
*/
private T parser2(ResponseBody value) throws IOException {
// String response = value.string();
String response;
response = value.string();
Log.e("colin", response + "------");
try {
// Logger.json(response); //打印日志,把响应转json字符串
JSONObject jsonObject = new JSONObject(response);
//TODO 判空,如果返回实体为null
// JSONObject jsonObject = resolveResponse(value);
int state = jsonObject.getInt("code");
if (state == STATE_FAILED) {
String msg = jsonObject.getString("message");
//return (T)msg;
throw new MyAPIException(state, msg);
} else if (state == STATE_FAILED2 || state == 407) {
String msg = jsonObject.getString("message");
//return (T)msg;
throw new MyAPIException(state, msg);
} else if (state == STATE_LOGIN_ERROR) {//登录各种情况:过期或被挤下线
String msg = jsonObject.getString("message");
// SPUtils.put("token",""); //把token存到本地sp
//跳转到登录页面
/*Intent intent=new Intent(MyApplication.getContext(), LoginAllWayActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK );
MyApplication.getContext().startActivity(intent);*/
//return (T)msg;
throw new MyAPILoginException(state, msg);
} else if (state == 410) {//提交订单,商品下架变动,弹框变动
// String data = jsonObject.getString("data");
throw new MyAPIException(state, response);
// if (mType == String.class) {
// return (T) data;
// } else {
// //return mGson.fromJson(data, mType);
// return mGson.fromJson(response, mType);
// }
} else {
String data = jsonObject.getString("data");
if (mType == String.class) {
return (T) data;
} else {
//return mGson.fromJson(data, mType);
return mGson.fromJson(response, mType);
}
}
} catch (JSONException e) {
throw new MyAPIException(0, "数据解析异常");
} finally {
value.close();
}
}
}
//没用上
/*private JSONObject resolveResponse(ResponseBody value) throws JSONException, IOException {
String result = value.toString();
if (StringUtils.isEmpty(result)) {
JSONObject resultJsonObject = new JSONObject();
resultJsonObject.put("code", STATE_FAILED);
resultJsonObject.put("message", "响应实体为空。");
LogUtils.e("服务端接口访问异常,返回数据实体为null");
return resultJsonObject;
}
return new JSONObject(result);
}*/
}
ApiCallBack
package com.example.testcsdnproject.network;
import android.util.Log;
import java.net.ConnectException;
import java.net.SocketTimeoutException;
import java.net.UnknownHostException;
import retrofit2.HttpException;
public abstract class ApiCallBack<T> {
protected abstract void onSuccess(T responseData ,String message);
protected abstract void onFailure(String error);
public void onSuccess(T responeData,int code, String message){
}
public void onResponse(ResponseBean<T> responseBean){
if (responseBean ==null){
//接口崩溃
onFailure("系统错误");
return;
}
//数据结果分类
if(responseBean.getCode() == ResponseBean.SUCCESS){
if (responseBean.getData() != null){
onSuccess(responseBean.getData(),responseBean.getMessage());
onSuccess(responseBean.getData(), responseBean.getCode(), responseBean.getMessage());
}else {
onSuccess(null, responseBean.getMessage());
}
}else {
onFailure(responseBean.getMessage());
}
}
public void onFailure(Throwable throwable){
throwable.printStackTrace();
Log.e("log", "throwable" + throwable.getMessage() + "," + throwable.toString());
if (throwable instanceof HttpException){
HttpException httpException = (HttpException) throwable;
int code = httpException.code();
if (code == 500 || code == 404){
onFailure("服务器出错");
}
}else if (throwable instanceof ConnectException) {
onFailure("网络断开,请打开网络!");
} else if (throwable instanceof SocketTimeoutException) {
onFailure("网络连接超时!");
} else if (throwable instanceof MyAPIException) {
onFailure(throwable.getMessage());
} /*else if (throwable instanceof MyAPILoginException) {//登录各种异常状态 被挤下线等...
onFailure(throwable.getMessage());
SharedPreferencesUtils.getInstance().clearUserInfoUser();
Intent intent=new Intent(MyApplication.getContext(), LoginActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
MyApplication.getContext().startActivity(intent);
}*/ else if (throwable instanceof UnknownHostException) {
onFailure("网络断开,请打开网络!");
} else {
onFailure(" " + throwable.getMessage());
}
}
}
MyApi(包含一个测试数据的接口)
package com.example.testcsdnproject.network;
import com.example.testcsdnproject.network.mvp.HomeLabelBean;
import java.util.List;
import io.reactivex.Observable;
import retrofit2.http.GET;
public class MyApi {
/**
* 网络接口前缀
*/
public static final String PREFIX = "服务器域名";
public interface Api{
/**
* 获取用户标签列表
* @return
* 一个测试数据的接口
*/
@GET("i/label/getList")
Observable<ResponseBean<List<HomeLabelBean>>>getLabelList();
//常用get post方法
// /**
// * 获取国家区号借口
// *
// * @return
// * @param// page 页码分页
// */
// @GET("countryCode/getCodeList/")
// Observable<ResponseBean<List<CountryBean>>> getCountry();
//
//
// /**
// * 获取3D展览 信息详情
// *
// * @param id 展览id
// * @param from
// * @return
// */
// @GET("exhibition/getDetail/")
// Observable<ResponseBean<WebContentBean>> getDetail(@Query("id") String id,
// @Query("from") String from);
//
//
// /**
// * 作品发布或取消发布
// *
// * @param workId 画展id
// * @return
// */
// @GET("artwork/release/{workId}")
// Observable<ResponseBean> publishWroks(@Path("workId") String workId);
//
//
//
// /**
// * 修改用户信息
// * @param body
// * @return
// */
// @PUT("users/modify/")
// Observable<ResponseBean> setUsersModify1(@Body RequestBody body);
//
// /**
// * 修改账户密码
// *
// * @param body
// * @return
// */
// @PUT("users/password/")
// Observable<ResponseBean> updataPwd(@Body RequestBody body);
//
//
// /**
// * 3D展览发布接口
// */
// @PUT("exhibition/release/{showId}")
// Observable<ResponseBean> publishPainting(@Path("showId") String showId);
//
//
//
// /**
// * 登入接口
// * @param mode (1:验证码,2:手机+密码,3:微信PC登录,4:微信移动端登录,5:app端微信登陆,6:小程序微信登陆,7:移动端APP一键登录)
// * @param phone
// * @param verifyCode
// * @param wechatCode
// * @param password
// * @param deviceToken
// * @param userId
// * @param timeStamp
// * @param countryCode
// * @param capKey
// * @param checkCode
// * @return
// */
// @FormUrlEncoded
// @POST("users/login/")
// Observable<ResponseBean<LoginBean>> Login(@Field("mode") String mode
// , @Field("phone") String phone
// , @Field("verifyCode") String verifyCode
// , @Field("wechatCode") String wechatCode
// , @Field("password") String password
// , @Field("deviceToken") String deviceToken
// , @Field("userId") String userId
// , @Field("timeStamp") String timeStamp
// , @Field("countryCode") String countryCode
// , @Field("capKey") String capKey
// , @Field("checkCode") String checkCode)
// ;
//
//
// /**
// * 修改展览发布状态
// * @param body
// * @return
// */
// @POST("i/artShow/releaseArtShowState")
// Observable<ResponseBean> releaseArtShowState(@Body RequestBody body);
//
//
// /**
// * 用户注销校验 验证码接口
// * 后端是用对象参数来接收请求时 用@FieldMap Map<String, String> maps封装请求参数
// * @param map
// * @return
// */
// @FormUrlEncoded
// @POST("a/logOffUser/checkVerificationCode/")
// Observable<ResponseBean>checkVerificationCodeBody(@FieldMap Map<String,String> map);
//
//
//
//
//
// /**
// * 删除接口 /exhibition/deleteArtShow
// */
// @HTTP(method = "DELETE", path = "exhibition/deleteArtShow/", hasBody = true)
// Observable<ResponseBean> deleteArtshow(@Body RequestBody body);
//
// /**
// * 删除接口收货地址
// *
// * @param id 地址id
// * @return
// */
// @HTTP(method = "DELETE", path = "shippingAddress/delete/", hasBody = true)
// Observable<ResponseBean> delAddress(@Query("id") int id);
//
//
// /**
// * 删除画作评论
// *
// * @return
// */
// @DELETE("artworkComments/delete")
// Observable<ResponseBean> deleteComment(@Query("id") int id);
//
//
}
}
ApiUtils
package com.example.testcsdnproject.network;
import android.util.Log;
import com.google.gson.Gson;
import java.io.IOException;
import java.net.URLDecoder;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import okhttp3.FormBody;
import okhttp3.Interceptor;
import okhttp3.MediaType;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
import okhttp3.logging.HttpLoggingInterceptor;
import retrofit2.Retrofit;
import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory;
public class ApiUtils {
private static MyApi.Api api;
private static Gson gson;
static {
//日志拦截器
HttpLoggingInterceptor httpLoggingInterceptor = new HttpLoggingInterceptor();
httpLoggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
OkHttpClient mOkHttpClient = new OkHttpClient.Builder()
.connectTimeout(20, TimeUnit.SECONDS)//链接超时15秒
.readTimeout(20, TimeUnit.SECONDS)
.addNetworkInterceptor(httpLoggingInterceptor)
.addInterceptor(new Interceptor() {
@Override
public Response intercept(Chain chain) throws IOException {
// Request request = chain.request().newBuilder()
// //在这里添加请求头或一些公共参数
// .addHeader("Accept", "application/vnd.mall.v1+json")
// .build();
// return chain.proceed(request);
Request originalRequest = chain.request();
Request.Builder builder = originalRequest.newBuilder();
// builder.addHeader("x-shinemi-auth", /*SPUtils.get("token", "")*/ "在消息头添加登录的token");
builder.addHeader("x-shinemi-auth", /*SPUtils.get("token", "")*/ "");
// String cookie = CookieManager.getInstance().getCookie(MyApi.BASE_URL);
// builder.addHeader("Cookie",CookieManager.getInstance().getCookie(MyApi.BASE_URL) );
if (originalRequest.method().equals("POST")/*|originalRequest.method().equals("PUT")*/) {
RequestBody requestBody = originalRequest.body();
if (requestBody instanceof PostJsonBody) {
String content = ((PostJsonBody) requestBody).getContent();
gson = new Gson();
HashMap<String, Object> hashMap = gson.fromJson(content, HashMap.class);
builder.post(getRequestBody(hashMap));
} else if (requestBody instanceof FormBody) {
FormBody formBody = (FormBody) requestBody;
LinkedHashMap<String, Object> hashMap = new LinkedHashMap<>();
for (int i = 0; i < formBody.size(); i++) {
hashMap.put(formBody.encodedName(i), URLDecoder.decode(formBody.encodedValue(i), "UTF-8"));
}
builder.post(getRequestBody(hashMap));
}
}
return chain.proceed(builder.build());
}
})
.build();
api = new Retrofit.Builder()
.baseUrl(MyApi.PREFIX)
.client(mOkHttpClient)
//.addConverterFactory(GsonConverterFactory.create())//添加Gson解析
.addConverterFactory(MyConverterFactory.create())//如果status状态码不同返回的数据类型不一样 自定义一个解析器
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())//添加RxJava2支持
.build()
.create(MyApi.Api.class);
}
/**
* 获取api
*
* @return
*/
public static MyApi.Api getApi() {
return api;
}
public static RequestBody getRequestBody(HashMap<String, Object> hashMap) {
Gson gson = new Gson();
Map<String, Object> params = new LinkedHashMap<>();
// params.put();
params.put("request", hashMap);
RequestBody requestBody = RequestBody.create(MediaType.parse("application/json; charset=utf-8"), gson.toJson(hashMap));
Log.e("colin", requestBody + "-----" + gson.toJson(params));
return requestBody;
}
}
BasePresenter
package com.example.testcsdnproject.network.mvp;
import java.lang.ref.WeakReference;
public class BasePresenter<View> {
private WeakReference<View> mViewWeakReference;
public BasePresenter(View view) {
mViewWeakReference = new WeakReference<>(view);
}
public void detach() {
if (mViewWeakReference != null) {
mViewWeakReference.clear();
mViewWeakReference = null;
}
}
public View getView() {
return mViewWeakReference == null ? null : mViewWeakReference.get();
}
}
完成====================
测试数据的实体类:
HomeLabelBean
package com.example.testcsdnproject.network.mvp;
import com.google.gson.annotations.SerializedName;
public class HomeLabelBean {
@SerializedName("id")
private int id;
@SerializedName("label")
private String label;
@SerializedName("createTime")
private Long createTime;
@SerializedName("updateTime")
private Long updateTime;
@SerializedName("state")
private int state;
@SerializedName("sort")
private Integer sort;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getLabel() {
return label;
}
public void setLabel(String label) {
this.label = label;
}
public Long getCreateTime() {
return createTime;
}
public void setCreateTime(Long createTime) {
this.createTime = createTime;
}
public Long getUpdateTime() {
return updateTime;
}
public void setUpdateTime(Long updateTime) {
this.updateTime = updateTime;
}
public int getState() {
return state;
}
public void setState(int state) {
this.state = state;
}
public Integer getSort() {
return sort;
}
public void setSort(Integer sort) {
this.sort = sort;
}
}
MVP模式:
HomeLabelListContract
package com.example.testcsdnproject.network.mvp;
import com.example.testcsdnproject.network.ApiCallBack;
import java.util.List;
public interface HomeLabelListContract {
interface Model{
void getHomeLabelList(ApiCallBack<List<HomeLabelBean>> callBack);
}
interface View{
void getHomeLabelListSuccess(List<HomeLabelBean> homeLabelBeanList);
void getHomeLabelListFail(String error);
}
interface Presenter{
void getHomeLabelList();
}
}
HomeLabelListModel
package com.example.testcsdnproject.network.mvp;
import com.example.testcsdnproject.network.ApiCallBack;
import com.example.testcsdnproject.network.ApiUtils;
import com.example.testcsdnproject.network.ResponseBean;
import java.util.List;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.functions.Consumer;
import io.reactivex.schedulers.Schedulers;
public class HomeLabelListModel implements HomeLabelListContract.Model{
@Override
public void getHomeLabelList(ApiCallBack<List<HomeLabelBean>> callBack) {
ApiUtils.getApi().getLabelList()
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Consumer<ResponseBean<List<HomeLabelBean>>>() {
@Override
public void accept(ResponseBean<List<HomeLabelBean>> listResponseBean) throws Exception {
callBack.onResponse(listResponseBean);
}
}, new Consumer<Throwable>() {
@Override
public void accept(Throwable throwable) throws Exception {
callBack.onFailure(throwable);
}
});
}
}
HomeLabelListPresenter
package com.example.testcsdnproject.network.mvp;
import com.example.testcsdnproject.network.ApiCallBack;
import java.util.List;
public class HomeLabelListPresenter extends BasePresenter<HomeLabelListContract.View> implements HomeLabelListContract.Presenter{
private HomeLabelListModel model;
public HomeLabelListPresenter(HomeLabelListContract.View view) {
super(view);
this.model =new HomeLabelListModel();
}
@Override
public void getHomeLabelList() {
model.getHomeLabelList(new ApiCallBack<List<HomeLabelBean>>() {
@Override
protected void onSuccess(List<HomeLabelBean> responseData, String message) {
if (getView()!=null){
getView().getHomeLabelListSuccess(responseData);
}
}
@Override
protected void onFailure(String error) {
if (getView()!=null){
getView().getHomeLabelListFail(error);
}
}
});
}
}
在activity中使用:
package com.example.testcsdnproject;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import com.example.testcsdnproject.network.mvp.HomeLabelBean;
import com.example.testcsdnproject.network.mvp.HomeLabelListContract;
import com.example.testcsdnproject.network.mvp.HomeLabelListPresenter;
import com.google.gson.Gson;
import java.util.List;
public class MainActivity extends AppCompatActivity implements HomeLabelListContract.View {
Button btn_get_lab;
TextView tv_lab;
private HomeLabelListPresenter presenter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
presenter = new HomeLabelListPresenter(this);
btn_get_lab = findViewById(R.id.btn_get_lab);
tv_lab = findViewById(R.id.tv_lab);
btn_get_lab.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
presenter.getHomeLabelList();
}
});
}
String labStr;
@Override
public void getHomeLabelListSuccess(List<HomeLabelBean> homeLabelBeanList) {
if (homeLabelBeanList!=null){
labStr = new Gson().toJson(homeLabelBeanList);
Log.d("labStr","labStr = "+labStr);
tv_lab.setText(labStr);
}
}
@Override
public void getHomeLabelListFail(String error) {
}
}
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<Button
android:id="@+id/btn_get_lab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="获取标签数据"
tools:layout_editor_absoluteX="16dp"
tools:layout_editor_absoluteY="60dp"
tools:ignore="MissingConstraints" />
<TextView
android:id="@+id/tv_lab"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:text="数据"
android:textColor="@color/black"
android:textSize="12sp"
app:layout_constraintTop_toBottomOf="@+id/btn_get_lab"
tools:ignore="MissingConstraints"
tools:layout_editor_absoluteX="0dp" />
</androidx.constraintlayout.widget.ConstraintLayout>
点击按钮,请求成功!
body传参:
JsonBean jsonBean = new JsonBean();
jsonBean.setHeadPortrait(imageurll);
String strjson = new Gson().toJson(jsonBean);
RequestBody requestBody = RequestBody.create(okhttp3.MediaType.parse("application/json; charset=utf-8"), strjson);
mPresent.EditUserinfo(requestBody);