当前位置:   article > 正文

okhttp3简单封装GET和POST请求工具类(https)_okhttp3 post 封装requestheadler

okhttp3 post 封装requestheadler

https://blog.csdn.net/fxjzzyo/article/details/78761373

 

简单封装了okhttp3的工具类以便于以后直接拿来使用。

使用的okhttp版本为:

compile 'com.squareup.okhttp3:okhttp:3.8.1'
1
该工具类的功能如下:

Get请求,同步方式获取网络数据
Post请求,同步方式获取数据
Get请求,异步方式获取网络数据
Post请求,异步方式获取数据
支持HTTPS请求,自动跳过证书验证
判断当前网络是否可用
其中Post请求提交的是键值对<String,String>1. 完整代码
 

  1. import android.content.Context;
  2. import android.net.ConnectivityManager;
  3. import android.net.NetworkInfo;
  4. import android.util.Log;
  5. import java.io.IOException;
  6. import java.security.SecureRandom;
  7. import java.security.cert.CertificateException;
  8. import java.security.cert.X509Certificate;
  9. import java.util.Iterator;
  10. import java.util.Map;
  11. import java.util.concurrent.TimeUnit;
  12. import javax.net.ssl.HostnameVerifier;
  13. import javax.net.ssl.SSLContext;
  14. import javax.net.ssl.SSLSession;
  15. import javax.net.ssl.SSLSocketFactory;
  16. import javax.net.ssl.TrustManager;
  17. import javax.net.ssl.X509TrustManager;
  18. import okhttp3.Call;
  19. import okhttp3.Callback;
  20. import okhttp3.OkHttpClient;
  21. import okhttp3.Request;
  22. import okhttp3.RequestBody;
  23. import okhttp3.Response;
  24. /**
  25.  * Created by fxjzzyo on 2017/7/12.
  26.  */
  27. public class NetUtils {
  28.     private static final byte[] LOCKER = new byte[0];
  29.     private static NetUtils mInstance;
  30.     private OkHttpClient mOkHttpClient;
  31.     private NetUtils() {
  32.         okhttp3.OkHttpClient.Builder ClientBuilder=new okhttp3.OkHttpClient.Builder();
  33.         ClientBuilder.readTimeout(20, TimeUnit.SECONDS);//读取超时
  34.         ClientBuilder.connectTimeout(6, TimeUnit.SECONDS);//连接超时
  35.         ClientBuilder.writeTimeout(60, TimeUnit.SECONDS);//写入超时
  36.         //支持HTTPS请求,跳过证书验证
  37.         ClientBuilder.sslSocketFactory(createSSLSocketFactory());
  38.         ClientBuilder.hostnameVerifier(new HostnameVerifier() {
  39.             @Override
  40.             public boolean verify(String hostname, SSLSession session) {
  41.                 return true;
  42.             }
  43.         });
  44.         mOkHttpClient=ClientBuilder.build();
  45.     }
  46.     /**
  47.      * 单例模式获取NetUtils
  48.      * @return
  49.      */
  50.     public static NetUtils getInstance() {
  51.         if (mInstance == null) {
  52.             synchronized (LOCKER) {
  53.                 if (mInstance == null) {
  54.                     mInstance = new NetUtils();
  55.                 }
  56.             }
  57.         }
  58.         return mInstance;
  59.     }
  60.     /**
  61.      * get请求,同步方式,获取网络数据,是在主线程中执行的,需要新起线程,将其放到子线程中执行
  62.      * @param url
  63.      * @return
  64.      */
  65.     public  Response getDataSynFromNet(String url) {
  66.         //1 构造Request
  67.         Request.Builder builder = new Request.Builder();
  68.         Request request=builder.get().url(url).build();
  69.         //2 将Request封装为Call
  70.         Call call = mOkHttpClient.newCall(request);
  71.         //3 执行Call,得到response
  72.         Response response = null;
  73.         try {
  74.             response = call.execute();
  75.         } catch (IOException e) {
  76.             e.printStackTrace();
  77.         }
  78.         return response;
  79.     }
  80.     /**
  81.      * post请求,同步方式,提交数据,是在主线程中执行的,需要新起线程,将其放到子线程中执行
  82.      * @param url
  83.      * @param bodyParams
  84.      * @return
  85.      */
  86.     public  Response postDataSynToNet(String url,Map<String,String> bodyParams) {
  87.         //1构造RequestBody
  88.         RequestBody body=setRequestBody(bodyParams);
  89.         //2 构造Request
  90.         Request.Builder requestBuilder = new Request.Builder();
  91.         Request request = requestBuilder.post(body).url(url).build();
  92.         //3 将Request封装为Call
  93.         Call call = mOkHttpClient.newCall(request);
  94.         //4 执行Call,得到response
  95.         Response response = null;
  96.         try {
  97.             response = call.execute();
  98.         } catch (IOException e) {
  99.             e.printStackTrace();
  100.         }
  101.         return response;
  102.     }
  103.     /**
  104.      * 自定义网络回调接口
  105.      */
  106.     public interface MyNetCall{
  107.         void success(Call call, Response response) throws IOException;
  108.         void failed(Call call, IOException e);
  109.     }
  110.     /**
  111.      * get请求,异步方式,获取网络数据,是在子线程中执行的,需要切换到主线程才能更新UI
  112.      * @param url
  113.      * @param myNetCall
  114.      * @return
  115.      */
  116.     public  void getDataAsynFromNet(String url, final MyNetCall myNetCall) {
  117.         //1 构造Request
  118.         Request.Builder builder = new Request.Builder();
  119.         Request request=builder.get().url(url).build();
  120.         //2 将Request封装为Call
  121.         Call call = mOkHttpClient.newCall(request);
  122.         //3 执行Call
  123.         call.enqueue(new Callback() {
  124.             @Override
  125.             public void onFailure(Call call, IOException e) {
  126.                 myNetCall.failed(call,e);
  127.             }
  128.             @Override
  129.             public void onResponse(Call call, Response response) throws IOException {
  130.                 myNetCall.success(call,response);
  131.             }
  132.         });
  133.     }
  134.     /**
  135.      * post请求,异步方式,提交数据,是在子线程中执行的,需要切换到主线程才能更新UI
  136.      * @param url
  137.      * @param bodyParams
  138.      * @param myNetCall
  139.      */
  140.     public  void postDataAsynToNet(String url, Map<String,String> bodyParams, final MyNetCall myNetCall) {
  141.         //1构造RequestBody
  142.         RequestBody body=setRequestBody(bodyParams);
  143.         //2 构造Request
  144.         Request.Builder requestBuilder = new Request.Builder();
  145.         Request request = requestBuilder.post(body).url(url).build();
  146.         //3 将Request封装为Call
  147.         Call call = mOkHttpClient.newCall(request);
  148.         //4 执行Call
  149.         call.enqueue(new Callback() {
  150.             @Override
  151.             public void onFailure(Call call, IOException e) {
  152.                 myNetCall.failed(call,e);
  153.             }
  154.             @Override
  155.             public void onResponse(Call call, Response response) throws IOException {
  156.                 myNetCall.success(call,response);
  157.             }
  158.         });
  159.     }
  160.     /**
  161.      * post的请求参数,构造RequestBody
  162.      * @param BodyParams
  163.      * @return
  164.      */
  165.     private RequestBody setRequestBody(Map<String, String> BodyParams){
  166.         RequestBody body=null;
  167.         okhttp3.FormBody.Builder formEncodingBuilder=new okhttp3.FormBody.Builder();
  168.         if(BodyParams != null){
  169.             Iterator<String> iterator = BodyParams.keySet().iterator();
  170.             String key = "";
  171.             while (iterator.hasNext()) {
  172.                 key = iterator.next().toString();
  173.                 formEncodingBuilder.add(key, BodyParams.get(key));
  174.                 Log.d("post http", "post_Params==="+key+"===="+BodyParams.get(key));
  175.             }
  176.         }
  177.         body=formEncodingBuilder.build();
  178.         return body;
  179.     }
  180.     /**
  181.      * 判断网络是否可用
  182.      * @param context
  183.      * @return
  184.      */
  185.     public static boolean isNetworkAvailable(Context context) {
  186.         ConnectivityManager cm = (ConnectivityManager) context
  187.                 .getSystemService(Context.CONNECTIVITY_SERVICE);
  188.         if (cm == null) {
  189.         } else {
  190.       //如果仅仅是用来判断网络连接
  191.       //则可以使用cm.getActiveNetworkInfo().isAvailable();
  192.             NetworkInfo[] info = cm.getAllNetworkInfo();
  193.             if (info != null) {
  194.                 for (int i = 0; i < info.length; i++) {
  195.                     if (info[i].getState() == NetworkInfo.State.CONNECTED) {
  196.                         return true;
  197.                     }
  198.                 }
  199.             }
  200.         }
  201.         return false;
  202.     }
  203.     /**
  204.      * 生成安全套接字工厂,用于https请求的证书跳过
  205.      * @return
  206.      */
  207.     public SSLSocketFactory createSSLSocketFactory() {
  208.         SSLSocketFactory ssfFactory = null;
  209.         try {
  210.             SSLContext sc = SSLContext.getInstance("TLS");
  211.             sc.init(null, new TrustManager[]{new TrustAllCerts()}, new SecureRandom());
  212.             ssfFactory = sc.getSocketFactory();
  213.         } catch (Exception e) {
  214.         }
  215.         return ssfFactory;
  216.     }
  217.     /**
  218.      * 用于信任所有证书
  219.      */
  220.     class TrustAllCerts implements X509TrustManager {
  221.         @Override
  222.         public void checkClientTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {
  223.         }
  224.         @Override
  225.         public void checkServerTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {
  226.         }
  227.         @Override
  228.         public X509Certificate[] getAcceptedIssuers() {
  229.             return new X509Certificate[0];
  230.         }
  231.     }
  232. }


2. 用法举例
推荐使用异步请求,因为已经把网络请求自动放到子线程了,用起来稍简单。而同步请求还需要自己new Thread+handler来做,几乎和原始的网络请求没区别了。因此这里举例就只举异步请求了。

异步GET请求
点击按钮登录 

  1. public void login(View view) {
  2.   final String account = etAccount.getText().toString();
  3.   final String pass = etPassword.getText().toString();
  4.   if (account.isEmpty() || pass.isEmpty()) {
  5.     Toast.makeText(this, "用户名或密码不能为空!", Toast.LENGTH_SHORT).show();
  6.            return;
  7.        }
  8.        if(!Global.isNetAvailable)
  9.        {
  10.            Toast.makeText(this, "网络不可用!", Toast.LENGTH_SHORT).show();
  11.            return;
  12.        }
  13.        //进度条
  14.        loginProgress.setVisibility(View.VISIBLE);
  15.        //获取网络工具类实例
  16.        NetUtils netUtils = NetUtils.getInstance();
  17.        //请求网络,一句代码搞定
  18.        netUtils.getDataAsynFromNet(Global.LOGIN + "?username=" + account + "&password=" + pass,
  19.                new NetUtils.MyNetCall() {
  20.                    @Override
  21.                    public void success(Call call, Response response) throws IOException {
  22.                        Log.i("tag", "success");
  23.                        String result = response.body().string();
  24.                        final ResponseBean responseBean = JSON.parseObject(result, ResponseBean.class);
  25.                        if (responseBean != null) {
  26.                            runOnUiThread(new Runnable() {
  27.                                @Override
  28.                                public void run() {
  29.                                    loginProgress.setVisibility(View.GONE);
  30.                                    String errcode = responseBean.getErrcode();
  31.                                    if (errcode.equals("0")) {//登录成功
  32.                                        //记录学号
  33.                                        Global.account = account;
  34.                                        //存储用户名密码
  35.                                        saveUserName(account, pass);
  36.                                        Intent intent = new Intent(LoginActivity.this, MainActivity.class);
  37.                                        startActivity(intent);
  38.                                        LoginActivity.this.finish();
  39.                                    } else {
  40.                                        Toast.makeText(LoginActivity.this, "请求失败!错误代码: " + errcode, Toast.LENGTH_SHORT).show();
  41.                                    }
  42.                                }
  43.                            });
  44.                        }
  45.                    }
  46.                    @Override
  47.                    public void failed(Call call, IOException e) {
  48.                        Log.i("tag", "failed");
  49.                        runOnUiThread(new Runnable() {
  50.                            @Override
  51.                            public void run() {
  52.                                loginProgress.setVisibility(View.GONE);
  53.                                Toast.makeText(LoginActivity.this, "请求失败!", Toast.LENGTH_SHORT).show();
  54.                            }
  55.                        });
  56.                    }
  57.                }
  58.        );
  59.    }


异步POST请求
点击按钮,提交数据

  1. public void postSelect() {
  2.         //确保选择了楼号
  3.         if (tvTargetBuilding.getText().toString().isEmpty()) {
  4.             Toast.makeText(getActivity(),"请选择楼号!",Toast.LENGTH_SHORT).show();
  5.             return;
  6.         }
  7.         //构造请求参数
  8.         Map<String, String> reqBody = new ConcurrentSkipListMap<>();
  9.         reqBody.put("num", "1");
  10.         reqBody.put("stuid", Global.account);
  11.         reqBody.put("buildingNo", selectBuilding + "");
  12.         //获取网络请求工具类实例
  13.         NetUtils netUtils = NetUtils.getInstance();
  14.         //提交数据
  15.         netUtils.postDataAsynToNet(Global.SELECT_ROOM, reqBody, new NetUtils.MyNetCall() {
  16.             @Override
  17.             public void success(Call call, Response response) throws IOException {
  18.                 Log.i("tag", "success");
  19.                 String result = response.body().string();
  20.                 Log.i("tag", "result: " + result);
  21.                 //解析数据
  22.                 JSONObject jsonObject1 = JSON.parseObject(result);
  23.                 if (jsonObject1 != null) {
  24.                     final int error_code = jsonObject1.getIntValue("error_code");
  25.                     getActivity().runOnUiThread(new Runnable() {
  26.                         @Override
  27.                         public void run() {
  28.                             Log.i("tag", "errcode: " + error_code);
  29.                             if (error_code == 0) {//提交成功
  30.                                 Toast.makeText(getActivity(), "选择成功!", Toast.LENGTH_SHORT).show();
  31.                                 //跳转到selectSuccessfragment
  32.                                 MainActivity.mainActivityInstance.switchFragment(getParentFragment(),SelectSuccessFragment.newInstance("", ""));
  33.                             } else {
  34.                                 Toast.makeText(getActivity(), "选择失败!错误代码: " + error_code, Toast.LENGTH_SHORT).show();
  35.                             }
  36.                         }
  37.                     });
  38.                 }
  39.             }
  40.             @Override
  41.             public void failed(Call call, IOException e) {
  42.                 Log.i("tag", "failed");
  43.                 getActivity().runOnUiThread(new Runnable() {
  44.                     @Override
  45.                     public void run() {
  46.                         Toast.makeText(getActivity(), "请求失败!", Toast.LENGTH_SHORT).show();
  47.                     }
  48.                 });
  49.             }
  50.         });
  51.     }


什么?还嫌代码太长?

其实很短的,除去注释和打印的日志以及一些不相干的部分(我这里的是一个实际的项目,所以涉及到一些其他的东西),你会发现代码很少,核心的代码就是一句。(这时候你可能要说,哼,是一句,但一句有十多行。。。拜托~不要那么懒啦好不好 -_-|||)

要注意的是获取数据后,更新UI要在主线程中。我这里使用的是runOnUiThread也可以用Handler。

用Handler后你会发现这一部分的代码很少了,因为只需要把获取的数据用Message发送到Handler处理就好了,这样就把代码分散开了

用runOnUiThread的好处是很直接,不过看起来代码都堆到一起,其实很方便的。

完结,撒花~

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/羊村懒王/article/detail/259325
推荐阅读
相关标签
  

闽ICP备14008679号