okhttp

 实现

    集成之前自然要导入okhttp的jar包,在android studio中可以很方便地在gradle中添加依赖

[html]  view plain  copy
  1. compile group: 'com.squareup.okhttp', name: 'okhttp', version: '2.7.5'  

    点击可查看okhttp的最新版本

    同步之后我们先来看看okhttp的基本用法(get):

[java]  view plain  copy
  1. new Thread(new Runnable() {  
  2.             @Override  
  3.             public void run() {  
  4.                 Request.Builder builder = new Request.Builder()  
  5.                         .url("http://www.baidu.com")   //指定网址  
  6.                         .get();          //指定请求类型  
  7.                 Request request = builder.build();  
  8.                 OkHttpClient client = new OkHttpClient();  
  9.                 try {  
  10.                     //实际进行请求的代码  
  11.                     Response response = client.newCall(request).execute();  
  12.                     //获取后端返回的json  
  13.                     String result = response.body().string();  
  14.                     Log.i("result", result);  
  15.                 } catch (IOException e) {  
  16.                     e.printStackTrace();  
  17.                 }  
  18.             }  
  19.         }).start();  

    讲道理okhttp已经大大简化了http访问的步骤,但是由于此为异步操作,需要新开一个线程进行,再加上try catch操作,无意中又增加了不少代码量。可以预见的是,日后执行其它的访问操作只是换了网址访问类型等变量而已,所以我们何不将重复代码整合在一起呢。

    整合的思路就是将以上的访问操作写入工具类中,而工具类采用单例模式,减少资源消耗。调用者只需传入网址封装request参数的RequestBody封装了访问成功后操作的回调函数三个参数便可以进行一次完整的http请求。是不是感到一阵熟悉,没错,就是照着ajax来的。还有一个关键点:访问类型,由于其数量有限,我们将其封装为枚举类,下文会进行详细讲解。

[java]  view plain  copy
  1. package zyz.com.httputiltest.http;  
  2.   
  3. import com.squareup.okhttp.OkHttpClient;  
  4. import com.squareup.okhttp.Request;  
  5. import com.squareup.okhttp.RequestBody;  
  6. import com.squareup.okhttp.Response;  
  7.   
  8. import java.io.IOException;  
  9.   
  10. /** 
  11.  * Created by zhuang_ge on 2017/11/13. 
  12.  */  
  13.   
  14. public class HttpUtil {  
  15.     private OkHttpClient client;//所有请求都由同一个client进行,减少资源消耗  
  16.     private String token;  
  17.     private SharedPreferences sp;//加入持久化,可以对一些特殊变量进行保存,比如用户id、用于登录验证的token等  
  18.     private SharedPreferences.Editor editor;  
  19.   
  20.     private HttpUtil() {  
  21.         client = new OkHttpClient();  
  22. //        sp = ContextApplication.getContext()  
  23. //                .getSharedPreferences("login_data", Context.MODE_PRIVATE);  
  24. //        editor = sp.edit();  
  25. //        token = sp.getString("token", "");  
  26.     }  
  27.   
  28.     private static HttpUtil httpUtil = null;  
  29.     //单例模式  
  30.     public static HttpUtil getInstance() {  
  31.         if (httpUtil == null) {  
  32.             httpUtil = new HttpUtil();  
  33.         }  
  34.         return httpUtil;  
  35.     }  
  36.   
  37.     public void sendRequestWithCallback(final RequestTypeEnum method, final String address, final RequestBody body, final HttpCallbackListener listener  
  38.     ) {  
  39.         new Thread(new Runnable() {  
  40.             @Override  
  41.             public void run() {  
  42.                 Request.Builder builder = new Request.Builder()  
  43.                         .url(address);  
  44.   
  45.                 switch (method) {  
  46.                     case POST:  
  47.                         builder.post(body);  
  48.                         break;  
  49.                     case PUT:  
  50.                         builder.put(body);  
  51.                         break;  
  52.                     case DELETE:  
  53.                         builder.delete(body);  
  54.                         break;  
  55.                     default:  
  56.                         builder.get();  
  57.                         break;  
  58.                 }  
  59.   
  60.                 Request request = builder.build();  
  61.                 try {  
  62.                     //实际进行请求的代码  
  63.                     Log.i("url = ", address);  
  64.                     Response response = client.newCall(request).execute();  
  65.                     token = response.header("token");  
  66.                     if (token == null) {  
  67.                         token = "b06804b910ea4f96a714a84d686d8583";  
  68.                         Log.i("""没有token使用默认token");  
  69.                     } else {  
  70.                         Log.i("""收到token:" + token);  
  71.                     }  
  72.   
  73.                       
  74.                     String result = response.body().string();  
  75.                     if (result != null && listener != null) {  
  76.                         //当response的code大于200,小于300时,视作请求成功  
  77.                         if (response.isSuccessful()) {  
  78.                             listener.onFinish(result);  
  79.                         } else {  
  80.                             listener.onError(new ServerException(result));  
  81.                         }  
  82.                     }  
  83.   
  84.                 } catch (IOException e) {  
  85.                     if (listener != null) {  
  86.                         listener.onError(e);  
  87.                     }  
  88.                 }  
  89.             }  
  90.         }).start();  
  91.   
  92.     }  
  93.   
  94.     public void post(final String address, RequestBody body, final HttpCallbackListener listener) {  
  95.         sendRequestWithCallback(RequestTypeEnum.POST, address, body, listener);  
  96.     }  
  97.   
  98.     public void get(String address, HttpCallbackListener listener) {  
  99.         sendRequestWithCallback(RequestTypeEnum.GET, address, null, listener);  
  100.     }  
  101.   
  102.     public void delete(String address, RequestBody body, HttpCallbackListener listener) {  
  103.         sendRequestWithCallback(RequestTypeEnum.DELETE, address, body, listener);  
  104.     }  
  105.   
  106.     public void put(String address, RequestBody body, HttpCallbackListener listener) {  
  107.         sendRequestWithCallback(RequestTypeEnum.PUT, address, body, listener);  
  108.     }  
  109.   
  110.   
  111. }  

    以上就是本工具类的核心代码,是不是看一眼就懂了?还有一些其它类也一并贴上:

    回调接口类:HttpCallbackListener.java

    

[java]  view plain  copy
  1. package zyz.com.httputiltest.http;  
  2. import android.util.Log;  
  3. import java.io.IOException;  
  4. public abstract class HttpCallbackListener {  
  5.   
  6.     public abstract void onFinish(String response);//正常访问之后进行的操作  
  7.   
  8.     public void onError(Exception e) {//出错后进行的操作  
  9.         if (e instanceof IOException) {  
  10.             // io 异常  
  11.             Log.e("网络错误", e.getMessage());  
  12.             return;  
  13.         }  
  14.     }  
  15. }  

    作为一个回调函数,在这里只需定义两个无需实现的函数就行。之前我用的是接口(interface)类,但遇到一个问题,对于调用方来说,执行onError时无法知悉出现的错误到底是网络本身的错误(连接不上服务器),还是服务器返回的错误(500)。换成抽象类之后,就可以写上一些判断语句,并对网络错误进行统一处理(比如弹个toast)。

    访问类型枚举类:RequestTypeEnum.java

[java]  view plain  copy
  1. public enum RequestTypeEnum {  
  2.     GET, POST, PUT, DELETE  
  3. }  

    由于需求里就这些,暂时就写下这四种类型了,有需要的同学可以自行添加。

    自定义错误类:

[java]  view plain  copy
  1. public class ServerException extends IOException {  
  2.     public ServerException(String message) {  
  3.         super(message);  
  4.     }  
  5. }  

    一看就懂,不再赘述。

    使用

    调用起来十分方便。编写一个界面验证一下


    按钮的点击事件

[java]  view plain  copy
  1. public void onClick(View view) {  
  2.         if(view.getId() == R.id.confirm) {  
  3.             String url = urlEdit.getText().toString().trim();  
  4.             HttpUtil.getInstance().get(url, new HttpCallbackListener() {  
  5.                 @Override  
  6.                 public void onFinish(final String response) {  
  7.                     runOnUiThread(new Runnable() {  
  8.                         @Override  
  9.                         public void run() {  
  10.                             contentEdit.setText(response);  
  11.                         }  
  12.                     });  
  13.                 }  
  14.                 @Override  
  15.                 public void onError(Exception e) {  
  16.                     super.onError(e);  
  17.                     Log.i("mainactivity","出错了");  
  18.                 }  
  19.             });  
  20.         }  
  21.     }  

    值得注意的是onError方法内部的书写有点门道,由于我们之前在抽象类中已经对网络错误进行统一处理并return,如果你想要自己再处理一下网络错误,则可以将代码写在super.onError之前。

    同时,因为安卓强制要求在UI主线程中进行视图刷新,所以我们需要在回调函数里调用runOnUIThread。想搞事情的可以在工具类中获取当前的context,将其强转为Activity,再调用Activity.runOnUIThread,在其中执行回调函数,这样一来所有的onFinish都是在Ui主线程中执行的。

    运行测试一下:


    成功的获取到了数据。

    最后贴一下源码地址,欢迎start和follow哦。源码地址

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值