OkHttp使用及工具类封装

来源:互联网 发布:mac怎么搜索硬盘文件 编辑:程序博客网 时间:2024/05/21 11:01

   今天主要跟大家说一下这个网络请求框架OKHttp

首先给大家推荐两个很好的博客(掘金):

http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2015/0106/2275.html(掘金)
http://blog.csdn.net/lmj623565791/article/details/47911083(张鸿洋博客)
有其他需要了解的去上面这两个网址;我就直接上代码了
在做任何OKHttp之前需要做的两件事就是:
依赖:
compile 'com.squareup.okhttp3:okhttp:3.4.2'
网络权限:
<uses-permission android:name="android.permission.INTERNET"/>
一:首先说一下get同步请求:(会阻塞线程)
  new Thread() {                    @Override                    public void run() {                        //1.创建OkHttpClient对象                        OkHttpClient okHttpClient = new OkHttpClient.Builder().readTimeout(5, TimeUnit.SECONDS).build();                        //2.通过build来创建一个Request请求,                        // 没有设置get方法,而是直接设置一个url地址,默认就是一个get方式的请求.                        final  Request request = new Request.Builder()                                .url(path)//这是一个接口地址                                .build();                        //3.创建一个call对象,参数就是Request请求对象,发送请求                        Call call = okHttpClient.newCall(request);                        //4.请求加入调度                        try {                            Response response = call.execute();                            Log.d("get",response.body().string());                        } catch (IOException e) {                            e.printStackTrace();                        }                    }                }.start();
二:get的异步请求:(不会阻塞线程)
 new Thread() {                    @Override                    public void run() {                        //1.创建OkHttpClient对象                        OkHttpClient okHttpClient = new OkHttpClient.Builder().build();                        //2.通过build来创建一个Request请求,                        // 没有设置get方法,而是直接设置一个url地址,默认就是一个get方式的请求.                        final Request request = new Request.Builder()                                .url(path)                                .build();                        //3.创建一个call对象,参数就是Request请求对象,发送请求                        Call call = okHttpClient.newCall(request);                        //4.请求加入调度                        call.enqueue(new Callback() {                            @Override //请求失败执行的方法                            public void onFailure(Call call, IOException e) {                            }                            //请求成功执行的方法                            // response就是从服务器得到的参数                            @Override                            public void onResponse(Call call, Response response) throws IOException {                                //response.body()可以得到任意类型,字符串,字节,等等.                                htmlStr = response.body().string();                                handler.sendEmptyMessage(0);//这里为了和上面区分开直接修改的TextView
                                 //注意:需要创建handler接受请求参数并显示                            }                        });                    }                }.start();
(post请求这里先不说了,基本和get一样,get不需要设置,默认就是get,而post需要设置一下:下面的上传图片中就用的post请求)
三:本地缓存:
 //通过点击事件,异步网络请求,拿到返回String数据,并进行本地缓存                new Thread(){                    @Override                    public void run() {                        //缓存大小                        int cacheSize=10*1024*1024;//10mb                        //创建cache对象,文件寻访到私有目录                        Cache cache = new Cache(getCacheDir(), cacheSize);                        //创建okhttpClint对象,进行本地缓存设置                        OkHttpClient okHttpClient = new OkHttpClient.Builder().cache(cache).build();                        Request.Builder builder = new Request.Builder();                        Request.Builder url = builder.url(path);                        Request request = url.build();                        //创建call对象                        Call call = okHttpClient.newCall(request);                        call.enqueue(new Callback() {                            //失败回调                            @Override                            public void onFailure(Call call, IOException e) {                            }                            //成功回调                            @Override                            public void onResponse(Call call, Response response) throws IOException {                            }                        });                    }                }.start();                break;
四:下载图片:
new Thread(){                    @Override                    public void run() {                        OkHttpClient okHttpClient = new OkHttpClient.Builder().build();                        Request request = new Request.Builder().url(path).build();                        Call call = okHttpClient.newCall(request);                        call.enqueue(new Callback() {                            @Override                            public void onFailure(Call call, IOException e) {                            }                            @Override//成功                            public void onResponse(Call call, Response response) throws IOException {                                byte[] bytes = response.body().bytes();                                final Bitmap bitmap = BitmapFactory.decodeByteArray(bytes, 0, bytes.length);                                runOnUiThread(new Runnable() {                                    @Override                                    public void run() {                                        mImageViewOkhttp.setImageBitmap(bitmap);
                                 //这里我直接设置给ImageView显示                                    }                                });                            }                        });                    }                }.start();
五:上传图片:
  /**                 * 当按钮点击时,执行okhttp上传图片到服务器                 *注意:有时候上传图片失败,是服务器规定还要上传一个key;                 */                //图片上传的接口地址                String url="http://123.206.14.104:8080/FileUploadDemo/FileUploadServlet";                //创建上传文件的对象                File file = new File(Environment.getExternalStorageDirectory(), "big.jpg");              //创建RequestBody封装参数                RequestBody fileBody = RequestBody.create(MediaType.parse("application/octet-stream"), file);                 //创建MultipartBody,给MultipartBody进行设置                MultipartBody multipartBody = new MultipartBody.Builder()                        .setType(MultipartBody.FORM)                        .addFormDataPart("image", "big.jpg", fileBody)                        .build();                /**                 * GET上传的数据一般是很小的并且安全性能不高的数据,                 * 而POST上传的数据适用于数据量大,数据类型复杂,数据安全性能要求高的地方                 */                //创建okhttp对象                OkHttpClient okHttpClient = new OkHttpClient.Builder()                        .connectTimeout(10, TimeUnit.SECONDS)                        .readTimeout(10, TimeUnit.SECONDS)                        .writeTimeout(10, TimeUnit.SECONDS)                        .build();                //创建Request对象                Request request = new Request.Builder()                        .url(url)                        .post(multipartBody)                        .build();                //上传完图片,得到服务器反馈数据                Call call = okHttpClient.newCall(request);                call.enqueue(new Callback() {                    @Override                    public void onFailure(Call call, IOException e) {                    }                    @Override                    public void onResponse(Call call, Response response) throws IOException {                        String string = response.body().string();                     //上传到服务器后,我们需要检查一下服务器有没有接受到,需要再请求一下,进行打印输出                    }                });                break;
下面说一下网络框架封装工具类:
(现在基本都是拿来用,只知道简单,但是大部分都不知道为什么要封装)
我自己罗列三点:
* 1.代码重复的多,使用过于冗余* 2.不用开子线程,直接就可以在主线程中使用我们的工具类来完成需求* 因此我们也不必要在使用过程中不必做线程间的交互,因此逻辑更简单* 3.节约内存,使所有网络请求都共用一个okhttpclient对象和handler对象
封装之前还需要注意的:
* 封装网络框架:* 1.每个网络框架,都有自己的特点,所以封装各不相同,因此在封装网络框架之前,要充分了解* 所封装的网络框架;* 2.解决代码冗余,我们可以根据自己的思路去对他安装自己的需求;* 3.封装完,网络框架性能要更优化,节约内存,逻辑处理变得简单(扁平化)
在封装OKHttp网络框架工具类时首先用到了几点:
单例模式,handler,接口回调等;
public class OkHttpUtils{    public static final long DEFAULT_MILLISECONDS = 10_000L;    private volatile static OkHttpUtils mInstance;    private OkHttpClient mOkHttpClient;    private Platform mPlatform;    public OkHttpUtils(OkHttpClient okHttpClient)    {        if (okHttpClient == null)        {            mOkHttpClient = new OkHttpClient();        } else        {            mOkHttpClient = okHttpClient;        }        mPlatform = Platform.get();    }    public static OkHttpUtils initClient(OkHttpClient okHttpClient)    {        if (mInstance == null)        {            synchronized (OkHttpUtils.class)            {                if (mInstance == null)                {                    mInstance = new OkHttpUtils(okHttpClient);                }            }        }        return mInstance;    }    public static OkHttpUtils getInstance()    {        return initClient(null);    }    public Executor getDelivery()    {        return mPlatform.defaultCallbackExecutor();    }    public OkHttpClient getOkHttpClient()    {        return mOkHttpClient;    }    public static GetBuilder get()    {        return new GetBuilder();    }    public static PostStringBuilder postString()    {        return new PostStringBuilder();    }    public static PostFileBuilder postFile()    {        return new PostFileBuilder();    }    public static PostFormBuilder post()    {        return new PostFormBuilder();    }    public static OtherRequestBuilder put()    {        return new OtherRequestBuilder(METHOD.PUT);    }    public static HeadBuilder head()    {        return new HeadBuilder();    }    public static OtherRequestBuilder delete()    {        return new OtherRequestBuilder(METHOD.DELETE);    }    public static OtherRequestBuilder patch()    {        return new OtherRequestBuilder(METHOD.PATCH);    }    public void execute(final RequestCall requestCall, Callback callback)    {        if (callback == null)            callback = Callback.CALLBACK_DEFAULT;        final Callback finalCallback = callback;        final int id = requestCall.getOkHttpRequest().getId();        requestCall.getCall().enqueue(new okhttp3.Callback()        {            @Override            public void onFailure(Call call, final IOException e)            {                sendFailResultCallback(call, e, finalCallback, id);            }            @Override            public void onResponse(final Call call, final Response response)            {                try                {                    if (call.isCanceled())                    {                        sendFailResultCallback(call, new IOException("Canceled!"), finalCallback, id);                        return;                    }                    if (!finalCallback.validateReponse(response, id))                    {                        sendFailResultCallback(call, new IOException("request failed , reponse's code is : " + response.code()), finalCallback, id);                        return;                    }                    Object o = finalCallback.parseNetworkResponse(response, id);                    sendSuccessResultCallback(o, finalCallback, id);                } catch (Exception e)                {                    sendFailResultCallback(call, e, finalCallback, id);                } finally                {                    if (response.body() != null)                        response.body().close();                }            }        });    }    public void sendFailResultCallback(final Call call, final Exception e, final Callback callback, final int id)    {        if (callback == null) return;        mPlatform.execute(new Runnable()        {            @Override            public void run()            {                callback.onError(call, e, id);                callback.onAfter(id);            }        });    }    public void sendSuccessResultCallback(final Object object, final Callback callback, final int id)    {        if (callback == null) return;        mPlatform.execute(new Runnable()        {            @Override            public void run()            {                callback.onResponse(object, id);                callback.onAfter(id);            }        });    }    public void cancelTag(Object tag)    {        for (Call call : mOkHttpClient.dispatcher().queuedCalls())        {            if (tag.equals(call.request().tag()))            {                call.cancel();            }        }        for (Call call : mOkHttpClient.dispatcher().runningCalls())        {            if (tag.equals(call.request().tag()))            {                call.cancel();            }        }    }    public static class METHOD    {        public static final String HEAD = "HEAD";        public static final String DELETE = "DELETE";        public static final String PUT = "PUT";        public static final String PATCH = "PATCH";    }}
上面的代码中涉及到几个常用的类:Request、Response和Call。
下面分别介绍: 
  Request 
每一个HTTP请求包含一个URL、一个方法(GET或POST或其他)、一些HTTP头。请求还可能包含一个特定内容类型的数据类的主体部分。 
Response 
响应是对请求的回复,包含状态码、HTTP头和主体部分。 
重写请求 
当将Request提交给OkHttp后,出于正确性和效率的考虑,OkHttp在传输请求之前会重写请求。 
OkHttp可能会在请求中添加缺少的请求头,包括”Content-Length”,”Transfer-Encoding”,”User-Agent”,”HOST”,”Connection”和”Content-Type”等。 
有些请求可能有缓存的响应。当缓存响应过时时,OkHttp可以做一个额外的GET请求获取最新的响应。这要求”If-Modified-Since”和”If-None-Match”头被添加。 
重写响应 
如果使用了透明压缩,OkHttp会丢弃”Content-Encoding”和”Content-Length”头,因为和解压后的响应主体不匹配。 
如果一个额外的GET请求成功了,那么网络和缓存中的响应将会合并。 
请求重定向 
当请求的URL移动了,web服务器会返回一个302的状态码并指明文件的新地址。OkHttp将会重定向获取最终的响应。 
请求重试 
有时连接会失败,那么OkHttp会重试别的路由。 
Call 
当重写、重定向等时,一个请求可能会产生多个请求和响应。OkHttp使用Call抽象出一个满足请求的模型,尽管中间可能会有多个请求或响应。执行Call有两种方式,同步或异步,这在上面已经介绍过了。 
Call可以在任何线程被取消。







原创粉丝点击