1.依赖添加:
implementation 'com.squareup.retrofit2:retrofit:2.4.0' 2.Retrofit请求类
package com.example.zb.retrofit2demo.retrofit; /** * Created by zb on 2019/4/19. */ import android.content.Context; import android.widget.Toast; import com.example.zb.retrofit2demo.R; import com.example.zb.retrofit2demo.bean.BaseResult; import com.example.zb.retrofit2demo.interfice.FileRequest; import com.example.zb.retrofit2demo.interfice.GetRequest; import com.example.zb.retrofit2demo.interfice.PostRequest; import com.example.zb.retrofit2demo.utils.Constant; import com.example.zb.retrofit2demo.utils.NetworkUtil; import com.google.gson.Gson; import com.google.gson.GsonBuilder; import java.io.File; import java.io.IOException; import java.net.ConnectException; import java.net.SocketTimeoutException; import java.security.cert.CertificateException; import java.util.HashMap; import java.util.Map; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; import javax.net.ssl.SSLSocketFactory; import javax.net.ssl.X509TrustManager; import okhttp3.MediaType; import okhttp3.OkHttpClient; import okhttp3.RequestBody; import okhttp3.ResponseBody; import retrofit2.Call; import retrofit2.Callback; import retrofit2.Response; import retrofit2.Retrofit; /** * Retrofit请求类 */ public class RetrofitRequest { private static int TIME_OUT = 30; // 30秒超时断开连接 // 自定义一个信任所有证书的TrustManager,添加SSLSocketFactory的时候要用到 private static X509TrustManager trustAllCert = new X509TrustManager() { @Override public void checkClientTrusted(java.security.cert.X509Certificate[] chain, String authType) throws CertificateException { } @Override public void checkServerTrusted(java.security.cert.X509Certificate[] chain, String authType) throws CertificateException { } @Override public java.security.cert.X509Certificate[] getAcceptedIssuers() { return new java.security.cert.X509Certificate[]{}; } }; private static SSLSocketFactory sslSocketFactory = new SSLSocketFactoryCompat(trustAllCert); // httpclient public static OkHttpClient client = new OkHttpClient.Builder() .sslSocketFactory(sslSocketFactory, trustAllCert) .connectTimeout(TIME_OUT, TimeUnit.SECONDS) .readTimeout(TIME_OUT, TimeUnit.SECONDS) .writeTimeout(TIME_OUT, TimeUnit.SECONDS) .build(); /** * 网络框架单例 * <p>因为示例中用到不同的接口地址,URL_BASE随便写了一个,如果是实际项目中,则设置为根路径即可</p> */ private static Retrofit retrofit = new Retrofit.Builder() .baseUrl(Constant.URL_BASE) .client(client) .build(); /** * 发送GET网络请求 * @param url 请求地址 * @param clazz 返回的数据类型 * @param resultHandler 回调 * @param <T> 泛型 */ public static <T extends BaseResult> void sendGetRequest(String url, final Class<T> clazz, final ResultHandler<T> resultHandler) { // 判断网络连接状况 if (resultHandler.isNetDisconnected()) { resultHandler.onAfterFailure(); return; } GetRequest getRequest = retrofit.create(GetRequest.class); // 构建请求 Call<ResponseBody> call = getRequest.getUrl(url); call.enqueue(new Callback<ResponseBody>() { @Override public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) { resultHandler.onBeforeResult(); try { ResponseBody body = response.body(); if (body == null) { resultHandler.onServerError(); return; } String string = body.string(); T t = new GsonBuilder().setDateFormat("yyyy-MM-dd HH:mm:ss").create().fromJson(string, clazz); resultHandler.onResult(t); } catch (IOException e) { e.printStackTrace(); resultHandler.onFailure(e); } } @Override public void onFailure(Call<ResponseBody> call, Throwable t) { resultHandler.onFailure(t); resultHandler.onAfterFailure(); } }); } /** * 发送post网络请求 * @param url 请求地址 * @param paramMap 参数列表 * @param clazz 返回的数据类型 * @param resultHandler 回调 * @param <T> 泛型 */ public static <T extends BaseResult> void sendPostRequest(String url, Map<String, String> paramMap, final Class<T> clazz, final ResultHandler<T> resultHandler) { // 判断网络连接状况 if (resultHandler.isNetDisconnected()) { resultHandler.onAfterFailure(); return; } PostRequest postRequest = retrofit.create(PostRequest.class); // 构建请求 Call<ResponseBody> call = postRequest.postMap(url, paramMap); call.enqueue(new Callback<ResponseBody>() { @Override public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) { resultHandler.onBeforeResult(); try { ResponseBody body = response.body(); if (body == null) { resultHandler.onServerError(); return; } String string = body.string(); T t = new Gson().fromJson(string, clazz); resultHandler.onResult(t); } catch (IOException e) { e.printStackTrace(); resultHandler.onFailure(e); } } @Override public void onFailure(Call<ResponseBody> call, Throwable t) { resultHandler.onFailure(t); resultHandler.onAfterFailure(); } }); } /** * 发送上传文件网络请求 * @param url 请求地址 * @param file 文件 * @param clazz 返回的数据类型 * @param resultHandler 回调 * @param <T> 泛型 */ public static <T extends BaseResult> void fileUpload(String url, File file, final Class<T> clazz, final ResultHandler<T> resultHandler) { // 判断网络连接状况 if (resultHandler.isNetDisconnected()) { resultHandler.onAfterFailure(); return; } FileRequest fileRequest = retrofit.create(FileRequest.class); Map<String, RequestBody> paramMap = new HashMap<>(); addMultiPart(paramMap, "file", file); // 构建请求 Call<ResponseBody> call = fileRequest.postFile(url, paramMap); call.enqueue(new Callback<ResponseBody>() { @Override public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) { resultHandler.onBeforeResult(); try { ResponseBody body = response.body(); if (body == null) { resultHandler.onServerError(); return; } String string = body.string(); T t = new Gson().fromJson(string, clazz); resultHandler.onResult(t); } catch (IOException e) { e.printStackTrace(); resultHandler.onFailure(e); } } @Override public void onFailure(Call<ResponseBody> call, Throwable t) { resultHandler.onFailure(t); resultHandler.onAfterFailure(); } }); } /** * 文件下载 * @param url 请求地址 * @param downloadHandler 回调接口 */ public static void fileDownload(String url, final DownloadHandler downloadHandler) { // 回调方法执行器,定义回调在子线程中执行,避免Callback返回到MainThread,导致文件下载出现NetworkOnMainThreadException ExecutorService executorService = Executors.newFixedThreadPool(1); // 网络框架 Retrofit retrofit = new Retrofit.Builder() .baseUrl(Constant.URL_BASE) .callbackExecutor(executorService) .build(); FileRequest fileRequest = retrofit.create(FileRequest.class); // 构建请求 Call<ResponseBody> call = fileRequest.download(url); call.enqueue(new Callback<ResponseBody>() { @Override public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) { if (response.isSuccessful()) { // 写入文件 downloadHandler.onBody(response.body()); } else { downloadHandler.onError(); } } @Override public void onFailure(Call<ResponseBody> call, Throwable t) { downloadHandler.onError(); } }); } /** * 添加多媒体类型 * * @param paramMap 参数对 * @param key 键 * @param obj 值 */ private static void addMultiPart(Map<String, RequestBody> paramMap, String key, Object obj) { if (obj instanceof String) { RequestBody body = RequestBody.create(MediaType.parse("text/plain;charset=UTF-8"), (String) obj); paramMap.put(key, body); } else if (obj instanceof File) { RequestBody body = RequestBody.create(MediaType.parse("multipart/form-data;charset=UTF-8"), (File) obj); paramMap.put(key + "\"; filename=\"" + ((File) obj).getName() + "", body); } } /** * 网络请求结果处理类 * @param <T> 请求结果封装对象 */ public static abstract class ResultHandler<T> { Context context; public ResultHandler(Context context) { this.context = context; } /** * 判断网络是否未连接 * * @return */ public boolean isNetDisconnected() { return NetworkUtil.isNetDisconnected(context); } /** * 请求成功之前 */ public abstract void onBeforeResult(); /** * 请求成功时 * * @param t 结果数据 */ public abstract void onResult(T t); /** * 服务器出错 */ public void onServerError() { // 服务器处理出错 Toast.makeText(context, R.string.net_server_error, Toast.LENGTH_SHORT).show(); } /** * 请求失败后的处理 */ public abstract void onAfterFailure(); /** * 请求失败时的处理 * * @param t */ public void onFailure(Throwable t) { if (t instanceof SocketTimeoutException || t instanceof ConnectException) { // 连接异常 if (NetworkUtil.isNetworkConnected(context)) { // 服务器连接出错 Toast.makeText(context, R.string.net_server_connected_error, Toast.LENGTH_SHORT).show(); } else { // 手机网络不通 Toast.makeText(context, R.string.net_not_connected, Toast.LENGTH_SHORT).show(); } } else if (t instanceof Exception) { // 功能异常 Toast.makeText(context, R.string.net_unknown_error, Toast.LENGTH_SHORT).show(); } } } /** * 文件下载回调 */ public interface DownloadHandler { /** * 接收到数据体 * @param body 响应体 */ public void onBody(ResponseBody body); /** * 文件下载出错 */ public void onError(); } }
3.Android4.4以下系统不支持TLS协议的适配
package com.example.zb.retrofit2demo.retrofit; import android.os.Build; import java.io.IOException; import java.net.InetAddress; import java.net.Socket; import java.net.UnknownHostException; import java.security.GeneralSecurityException; import java.util.Arrays; import java.util.HashSet; import java.util.LinkedList; import java.util.List; import javax.net.ssl.SSLContext; import javax.net.ssl.SSLSocket; import javax.net.ssl.SSLSocketFactory; import javax.net.ssl.X509TrustManager; /** * Android4.4以下系统不支持TLS协议的适配 */ public class SSLSocketFactoryCompat extends SSLSocketFactory { private SSLSocketFactory defaultFactory; // Android 5.0+ (API level21) provides reasonable default settings // but it still allows SSLv3 // https://developer.android.com/about/versions/android-5.0-changes.html#ssl static String protocols[] = null, cipherSuites[] = null; static { try { SSLSocket socket = (SSLSocket) SSLSocketFactory.getDefault().createSocket(); if (socket != null) { /* set reasonable protocol versions */ // - enable all supported protocols (enables TLSv1.1 and TLSv1.2 on Android <5.0) // - remove all SSL versions (especially SSLv3) because they're insecure now List<String> protocols = new LinkedList<>(); for (String protocol : socket.getSupportedProtocols()) if (!protocol.toUpperCase().contains("SSL")) protocols.add(protocol); SSLSocketFactoryCompat.protocols = protocols.toArray(new String[protocols.size()]); /* set up reasonable cipher suites */ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) { // choose known secure cipher suites List<String> allowedCiphers = Arrays.asList( // TLS 1.2 "TLS_RSA_WITH_AES_256_GCM_SHA384", "TLS_RSA_WITH_AES_128_GCM_SHA256", "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256", "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256", "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384", "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256", "TLS_ECHDE_RSA_WITH_AES_128_GCM_SHA256", // maximum interoperability "TLS_RSA_WITH_3DES_EDE_CBC_SHA", "TLS_RSA_WITH_AES_128_CBC_SHA", // additionally "TLS_RSA_WITH_AES_256_CBC_SHA", "TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA", "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA", "TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA", "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA"); List<String> availableCiphers = Arrays.asList(socket.getSupportedCipherSuites()); // take all allowed ciphers that are available and put them into preferredCiphers HashSet<String> preferredCiphers = new HashSet<>(allowedCiphers); preferredCiphers.retainAll(availableCiphers); /* For maximum security, preferredCiphers should *replace* enabled ciphers (thus disabling * ciphers which are enabled by default, but have become unsecure), but I guess for * the security level of DAVdroid and maximum compatibility, disabling of insecure * ciphers should be a server-side task */ // add preferred ciphers to enabled ciphers HashSet<String> enabledCiphers = preferredCiphers; enabledCiphers.addAll(new HashSet<>(Arrays.asList(socket.getEnabledCipherSuites()))); SSLSocketFactoryCompat.cipherSuites = enabledCiphers.toArray(new String[enabledCiphers.size()]); } } } catch (IOException e) { throw new RuntimeException(e); } } public SSLSocketFactoryCompat(X509TrustManager tm) { try { SSLContext sslContext = SSLContext.getInstance("TLS"); sslContext.init(null, (tm != null) ? new X509TrustManager[]{tm} : null, null); defaultFactory = sslContext.getSocketFactory(); } catch (GeneralSecurityException e) { throw new AssertionError(); // The system has no TLS. Just give up. } } private void upgradeTLS(SSLSocket ssl) { // Android 5.0+ (API level21) provides reasonable default settings // but it still allows SSLv3 // https://developer.android.com/about/versions/android-5.0-changes.html#ssl if (protocols != null) { ssl.setEnabledProtocols(protocols); } if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP && cipherSuites != null) { ssl.setEnabledCipherSuites(cipherSuites); } } @Override public String[] getDefaultCipherSuites() { return cipherSuites; } @Override public String[] getSupportedCipherSuites() { return cipherSuites; } @Override public Socket createSocket(Socket s, String host, int port, boolean autoClose) throws IOException { Socket ssl = defaultFactory.createSocket(s, host, port, autoClose); if (ssl instanceof SSLSocket) upgradeTLS((SSLSocket) ssl); return ssl; } @Override public Socket createSocket(String host, int port) throws IOException, UnknownHostException { Socket ssl = defaultFactory.createSocket(host, port); if (ssl instanceof SSLSocket) upgradeTLS((SSLSocket) ssl); return ssl; } @Override public Socket createSocket(String host, int port, InetAddress localHost, int localPort) throws IOException, UnknownHostException { Socket ssl = defaultFactory.createSocket(host, port, localHost, localPort); if (ssl instanceof SSLSocket) upgradeTLS((SSLSocket) ssl); return ssl; } @Override public Socket createSocket(InetAddress host, int port) throws IOException { Socket ssl = defaultFactory.createSocket(host, port); if (ssl instanceof SSLSocket) upgradeTLS((SSLSocket) ssl); return ssl; } @Override public Socket createSocket(InetAddress address, int port, InetAddress localAddress, int localPort) throws IOException { Socket ssl = defaultFactory.createSocket(address, port, localAddress, localPort); if (ssl instanceof SSLSocket) upgradeTLS((SSLSocket) ssl); return ssl; } }
3.文件上传请求封装
package com.example.zb.retrofit2demo.interfice; import java.util.Map; import okhttp3.RequestBody; import okhttp3.ResponseBody; import retrofit2.Call; import retrofit2.http.GET; import retrofit2.http.Multipart; import retrofit2.http.POST; import retrofit2.http.PartMap; import retrofit2.http.Streaming; import retrofit2.http.Url; /** * 文件上传请求封装 */ public interface FileRequest{ /** * 上传文件请求 * @param url URL路径 * @param paramMap 请求参数 * @return */ @Multipart @POST Call<ResponseBody> postFile(@Url String url, @PartMap Map<String, RequestBody> paramMap); /** * 下载文件get请求 * @param url 链接地址 * @return */ @Streaming @GET Call<ResponseBody> download(@Url String url); }
4.get请求封装
package com.example.zb.retrofit2demo.interfice; import okhttp3.ResponseBody; import retrofit2.Call; import retrofit2.http.GET; import retrofit2.http.Url; /** * get请求封装 */ public interface GetRequest { /** * 发送Get请求请求 * @param url URL路径 * @return */ @GET Call<ResponseBody> getUrl(@Url String url); }
5.Post请求封装
package com.example.zb.retrofit2demo.interfice; import java.util.Map; import okhttp3.ResponseBody; import retrofit2.Call; import retrofit2.http.FieldMap; import retrofit2.http.FormUrlEncoded; import retrofit2.http.POST; import retrofit2.http.Url; /** * Post请求封装 */ public interface PostRequest { /** * 发送Post请求 * @param url URL路径 * @param requestMap 请求参数 * @return */ @FormUrlEncoded @POST Call<ResponseBody> postMap(@Url String url, @FieldMap Map<String, String> requestMap); }
6.get调用代码处理
private void onGet() { // 这里放显示loading String url = Constant.URL_WEATHER; url += "?city=北京"; RetrofitRequest.sendGetRequest(url, WeatherResult2.class, new RetrofitRequest.ResultHandler<WeatherResult2>(this) { @Override public void onBeforeResult() { // 这里可以放关闭loading } @Override public void onResult(WeatherResult2 weatherResult2) { String s = new Gson().toJson(weatherResult2); MyLog.i("get------", s); } @Override public void onAfterFailure() { // 这里可以放关闭loading } }); }
7.post调用代码处理
private void onPost() { // 这里放显示loading progressDialog.show(); String url = Constant.URL_BASE1; Map<String, String> paramMap = new HashMap<>(1); paramMap.put("code", "admin"); paramMap.put("password", "123456"); RetrofitRequest.sendPostRequest(url, paramMap, WeatherResult.class, new RetrofitRequest.ResultHandler<WeatherResult>(this) { @Override public void onBeforeResult() { // 这里可以放关闭loading progressDialog.dismiss(); } @Override public void onResult(WeatherResult weatherResult) { progressDialog.dismiss(); String weather = new Gson().toJson(weatherResult); MyLog.i("retrofit------", weather); MyLog.i("errMsg------", weatherResult.getErrMsg()); MyLog.i("Name------", weatherResult.getResult().getName()); MyLog.i("password------", weatherResult.getResult().getPassword()); } @Override public void onAfterFailure() { // 这里可以放关闭loading progressDialog.dismiss(); } }); }
github地址:https://github.com/b888zhang/Retrofit2Demo