简介

okhttp是一个第三方类库,用于android中请求网络。这是一个开源项目,是安卓端最火热的轻量级框架,由移动支付Square公司贡献(该公司还贡献了Picasso和LeakCanary) 。用于替代HttpUrlConnection和Apache HttpClient(android API23 里已移除HttpClient)。

  • 官网网址:OKHttp官网
  • OkHttp github地址:https://github.com/square/okhttp
  • OkHttp jar包下载: https://search.maven.org/remote_content?g=com.squareup.okhttp3&a=okhttp&v=LATEST
  • 参考博客:https://blog.csdn.net/lmj623565791/article/details/47911083

依赖

implementation 'com.squareup.okhttp3:okhttp:3.11.0'


 

同步请求方式(get请求)

步骤一  创建请求接口网址

我使用了http://www.sosoapi.com/ 来创建了一个访问接口,用来验证OkHttp是否请求成功。如果你有兴趣了解,可以直接进入网站,里面有详细的demo演示。后续我将不在赘述这段。

我在请求响应里添加了一段JSON数据:

[    {        "name": "get测试",        "content": "你成功获取了数据"    }]

步骤二  创建JSON解析方法

这里我写一下解析JSON数据的方法,来解析get或者post得到的JSON数据。后续我将不在赘述这段。

/**     * JSON 解析方法     * @param jsonData     * @return     */    public String readJSONContent(String jsonData){        try {            StringBuffer sb = new StringBuffer();            JSONArray jsonArray = new JSONArray(jsonData);            for (int i=0;i){                JSONObject jsonObject = jsonArray.getJSONObject(i);                sb.append(jsonObject.getString("name")+"\n");                sb.append(jsonObject.getString("content")+"\n");            }            return sb.toString();        } catch (JSONException e) {            Log.e("JSONException错误", "readContent: "+e.toString());            return e.toString();        }    }

步骤三  创建OkHttp 同步请求

/**     * 同步请求     */    public void synchro(){        Thread thread = new Thread(new Runnable() {            @Override            public void run() {                OkHttpClient okHttpClient = new OkHttpClient();//创建单例                Request request = new Request.Builder()//创建请求                        .url("http://www.sosoapi.com/pass/mock/12003/test/gettest")                        .build();                try {                    Response response = okHttpClient.newCall(request).execute();//执行请求                    mContent = response.body().string();//得到返回响应,注意response.body().string() 只能调用一次!                    runOnUiThread(new Runnable() {                        @Override                        public void run() {                            mtextView.setText(readJSONContent(mContent));                        }                    });                } catch (IOException e) {                    e.printStackTrace();                    Log.e("OkHttpActivity", e.toString() );                }            }        });        thread.start();    }

注意!response.body().string() 只能调用一次! 因为响应主体 RessponseBody 持有的资源可能会很大,所以 OkHttp 并不会将其直接保存到内存中,只是持有数据流连接。只有当我们需要时,才会从服务器获取数据并返回。同时,考虑到应用重复读取数据的可能性很小,所以将其设计为一次性流(one-shot),读取后即 '关闭并释放资源'

 

效果图:

 

 


 

异步请求方式(get请求)

注意1:异步请求方式,请求的回调会在子线程里,所以如果需要更新UI你需要切换到主线程。且你不需要在new 一个线程包裹这个异步请求了。另外如何切换到主线程请使用 Handler 例子:

注意2:在异步请求方法里,请不要将 public void onResponse(Call call, final Response response)回调里的response回调数据放到UI线程里解析,因为有一个天坑,有可能在UI线程里解析的时候response里面却还没有塞入数据(我也觉得很神奇,不知道写okhttp的公司是怎么想的,为什么不处理完所有数据在提供回调)

 

private Handler mHandler = new Handler(Looper.getMainLooper());
            mHandler.post(new Runnable() {                    @Override                    public void run() {                        //主线程                    }                });    

创建异步请求

     /**     * get异步请求     */      public void asynchronous(){          OkHttpClient okHttpClient = new OkHttpClient();          Request request = new Request.Builder()                  .url("http://www.sosoapi.com/pass/mock/12003/test/gettest")                  .build();          okHttpClient.newCall(request).enqueue(new Callback() {              @Override              public void onFailure(Call call, IOException e) {                  //失败回调              }              @Override              public void onResponse(Call call, final Response response) throws IOException {
            mContent = readJSONContent(response.body().string());//注意response.body().string() 只能调用一次!
//响应成功,这个回调在子线程中,所以不需要创建线程 if (response.isSuccessful()){ //isSuccessful方法:如果代码位于(200…300)中,则返回true,这意味着请求已成功接收 runOnUiThread(new Runnable() { @Override public void run() { try { //因为在子线程,所以我们需要回到主线程中更新UI数据 mtextView.setText(mContent); } catch (IOException e) { e.printStackTrace(); } } }); } } }); }

 


 

Post请求

post请求也同时有同步与异步方法,与上面一致,所以这里就不展示了,下面我们来看看post请求发送

/**     * post请求     */    public void post(){        new Thread(new Runnable() {            @Override            public void run() {                //实例                OkHttpClient okHttpClient = new OkHttpClient();                //创建post请求数据表单                RequestBody requestBody = new FormBody.Builder()                        .add("name","请求post")                        .add("password","123456")                        .build();                //创建请求                final Request request = new Request.Builder()                        .url("http://www.sosoapi.com/pass/mock/12003/test/posttest")                        .post(requestBody)//添加post请求                        .build();                try {                    //发送请求得到响应                    final Response response = okHttpClient.newCall(request).execute();                    runOnUiThread(new Runnable() {                        @Override                        public void run() {                            try {                                mtextView.setText(readJSONContent(response.body().string()));//注意response.body().string() 只能调用一次!                            } catch (IOException e) {                                e.printStackTrace();                            }                        }                    });                } catch (IOException e) {                    e.printStackTrace();                }            }        }).start();    }

效果图:

取消网络请求

取消okhttp的网络请求很简单只需要

call.cancel();

如何鉴别是网络异常还是主动取消,请求取消的回调在onFailure(Call call, IOException e)里回调,这个时候我们需要再次判断onFailure里回调的是我们自己主动取消的还是网络异常报错的

mCall.enqueue(new Callback() {//发送请求    @Override    public void onFailure(final Call call, final IOException e) {        if (call.isCanceled()){            listener.onCancel();        }else {            listener.onFailure(call, e);        }    }     //省略下面代码...

 


 

 

RequestBody创建

RequestBody是okhttp  post发送数据配置类.在这之前我们先了解下回顾一下body类型

 

http有四种body类型,Content-Type POST提交数据的方式:
  • application/x-www-form-urlencoded 表单数据
  • multipart/form-data 表单文件上传
  • application/json 序列化JSON数据
  • text/xml XML数据

这些body类型需要在http header头部就写上,但是okhttp不需要我们手动在header写上类型了.okhttp提供了FormBody和MultipartBody的类型,方便你的快速创建 application/x-www-form-urlencoded 与 multipart/form-data

FormBody 创建方式

/**     * 此body是 默认application/x-www-form-urlencoded,你可以进入FormBody类查看,第一行静态常量就是这个     */   public void FormBody(){       FormBody.Builder builder = new FormBody.Builder();       builder.add("key","content");       builder.build();   }

MultipartBody 创建方式

 

/**     * multipart/form-data     */   public void MultipartBody(){       RequestBody requestBody = new RequestBody() {           @Override           public MediaType contentType() {               return null;           }           @Override           public void writeTo(BufferedSink sink) throws IOException {               //上传流 sink.write()           }       };       MultipartBody.Builder builder = new MultipartBody.Builder();       builder.addFormDataPart("key","content");//表单数据       builder.addFormDataPart("file_key","/path/image.jpg",requestBody);//文件数据       MultipartBody multipartBody = builder.build();   }

手动创建4种body

当然,有特殊需求你还可以添加手动其他body类型,create也支持好几种数据的上传形式

 /**     * 手动创建4种body     */   public void RequestBody(){       RequestBody applicationFormUrlencodedBody = RequestBody.create(MediaType.parse("application/x-www-form-urlencoded; charset=utf-8"),new String("demo").getBytes());       RequestBody multipartBody = RequestBody.create(MediaType.parse("multipart/form-data; charset=utf-8"),new File("/path/image.jpg"));       RequestBody jsonBody = RequestBody.create(MediaType.parse("application/json; charset=utf-8"),"content");       RequestBody textbody = RequestBody.create(MediaType.parse("text/xml; charset=utf-8"),"content");   }

 


 

实现OkHttpClient客户端单例模式

public class OkHttpClientCreate {    private static final boolean IS_RETRY = false;//失败是否重连    private static final int CONNECT_TIME = 10;//设置连接超时时间 单位:秒    private static final int READ_TIME = 10;//设置读取超时时间    private static final int WRITE_TIME = 10;//设置写入超时间    private static OkHttpClient mOkHttpClient;    public static OkHttpClient CreateClient(){        if (mOkHttpClient == null){            return mOkHttpClient = new OkHttpClient.Builder()                    .retryOnConnectionFailure(IS_RETRY)                    .connectTimeout(CONNECT_TIME,TimeUnit.SECONDS)//连接超时                    .readTimeout(READ_TIME,TimeUnit.SECONDS)//读取超时                    .writeTimeout(WRITE_TIME,TimeUnit.SECONDS)//写入超时//                    .callTimeout()//呼叫超时,设置此参数为整体流程请求的超时时间//                    .addInterceptor() //设置拦截器//                    .authenticator() //设置认证器//                    .proxy()//设置代理                    .build();        }        return mOkHttpClient;    }    public static void destroy(){        mOkHttpClient = null;    }    }

更多相关文章

  1. 一句话锁定MySQL数据占用元凶
  2. Android(安卓)Hawk数据库 github开源项目
  3. ListView改变里面TextView的字体颜色
  4. Android9.0 SIM卡初始化---更新数据(代码 高通9.0代码)
  5. Android(安卓)ContentProvider和getContentResolver
  6. Android(安卓)天气预报(使用okHttp、AsyncTask访问和风天气并Gosn
  7. React Native学习第三天
  8. Android, BaseAdapter 处理大数据量时的优化
  9. Android(安卓)9.0 适配

随机推荐

  1. Android实训案例(二)——Android下的CMD
  2. Android(安卓)系统分析[1]
  3. iOS 与 Android(安卓)之战,乔布斯是否正在
  4. Android(安卓)自定义动画 单个View平面位
  5. 如何学习Android及如何利用android来赚钱
  6. [置顶] 随了Android的大流,站入Google阵营
  7. 寻找卓越的(Android)软件工程师,可解你燃眉
  8. 【eoe Android特刊】第二十五期 Android(
  9. Android图形显示系统——下层显示4:图层合
  10. 转行Android后第一次面试某鹅被坑,那些一