Android OkHttp 框架学习

来源:互联网 发布:js调用另一个js的函数 编辑:程序博客网 时间:2024/05/29 06:54

官方介绍:http://square.github.io/okhttp/
http://square.github.io/retrofit/
引用:
AndroidStudio:
compile 'com.squareup.okhttp3:okhttp:3.6.0'
compile 'com.squareup.okio:okio:1.5.0'

Eclipse:
LastedOkHttpJar
okioJar

注意:最新版本的okhttp已经内置了okio包)

一:服务的初始化
官方不建议我们创建多个HttpClient,对系统资源消耗较大,如果实在有需求可以clone。关于一些常用的初始化设置如下:

        client = new OkHttpClient();        OkHttpClient.Builder b = client.newBuilder();        b.connectTimeout(MAX_TIMEOUT, TimeUnit.SECONDS);        b.writeTimeout(MAX_TIMEOUT, TimeUnit.SECONDS);        b.readTimeout(MAX_TIMEOUT, TimeUnit.SECONDS);        b.hostnameVerifier(new HostnameVerifier() {            @Override            public boolean verify(String s, SSLSession sslSession) {                return true;            }        });        client = b.build();

二:Get请求

import java.io.IOException;import okhttp3.MediaType;import okhttp3.OkHttpClient;import okhttp3.Request;import okhttp3.RequestBody;import okhttp3.Response;public class Example{    public class GetExample {        OkHttpClient client = new OkHttpClient();        String run(String url) throws IOException {            Request request = new Request.Builder()                    .url(url)                    .build();            try (Response response = client.newCall(request).execute()){                return response.body().string();            }        }    }    public static void test() throws IOException {        GetExample example = new GetExample();        String response = example.run("https://raw.github.com/square/okhttp/master/README.md");        System.out.println(response);    }}

OkHttp的Response实现了lang.AutoCloseable接口(Java7新特性try-with-resources)

  1. 发送一个请求的步骤,首先构造一个Request对象,参数最起码有个url,当然你可以通过Request.Builder设置更多的参数比如:header、method等。
  2. 通过request的对象去构造得到一个Call对象,类似于将你的请求封装成了任务,既然是任务,就会有execute()和cancel()等方法。
  3. 我们这里是阻塞的方式去执行,当然也支持异步的方式,你也可以直接调用call.enqueue()。将call加入调度队列,然后等待任务执行完成,我们在Callback中即可得到结果Response。

三:Post请求

public class PostExample {//可以定义多种多媒体传输类型        public static final MediaType JSON                = MediaType.parse("application/json; charset=utf-8");        String run(String url, String json) throws IOException {            RequestBody body = RequestBody.create(JSON, json);            //构造form表单数据请求方式            //FormBody.Builder body = new //FormBody.Builder();            //body.add(key, val);            Request request = new Request.Builder()                    .url(url)                    .tag(tag);                    .post(body)//.post(body.build())                    .build();            Response response = client.newCall(request).execute();            //或者采用异步方式请求            //请求加入调度        client.newCall(request).enqueue(new Callback()        {            @Override            public void onFailure(Request request, IOException e)            {            }            @Override            public void onResponse(final Response response) throws IOException            {                    //String htmlStr =  response.body().string();            }        });            return response.body().string();        }    }    public static void test() throws IOException {        PostExample example = new PostExample();        String json = "{}";        String response = example.run("http://www.roundsapp.com/post", json);        System.out.println(response);    }

注意:

  • onResponse回调的参数是response,一般情况下,比如我们希望获得返回的字符串,可以通过response.body().string()获取;如果希望获得返回的二进制字节数组,则调用response.body().bytes();如果你想拿到返回的inputStream,则调用response.body().byteStream()。
    看到这,你可能会奇怪,竟然还能拿到返回的inputStream,看到这个最起码能意识到一点,这里支持大文件下载,有inputStream我们就可以通过IO的方式写文件。不过也说明一个问题,这个onResponse执行的线程并不是UI线程。的确是的,如果你希望操作控件,还是需要使用handler等,我更喜欢用RxAndroid来封装请求和回调过程。或者可以结合Retrofit来封装网络请求更快捷。
@Overridepublic void onResponse(final Response response) throws IOException{      final String res = response.body().string();      runOnUiThread(new Runnable()      {          @Override          public void run()          {            mTv.setText(res);          }      });}
Observable<Result> obs = Observable.create(new Observable.OnSubscribe<Result>()        {            @Override            public void call(Subscriber<? super Result> subscriber)            {               try(Response response = http.syncExcute(url, p, tag))                {                    if (response == null)                        return;                    if (response.isSuccessful())                    {                        String str = response.body().string();                        L.i("HTTP", "RESPONSE>" + str+"   url==="+url);                        Result r = analyze(str, response.request().url().toString(), null);                        subscriber.onNext(r);                    } else                        throw new Exception(" (" + response.code() + ")");                } catch (Exception e)                {                    subscriber.onError(e);                }            }        });        obs = obs.subscribeOn(Schedulers.io());        obs = obs.observeOn(AndroidSchedulers.mainThread());        obs.subscribe(new Observer<Result>()        {            @Override            public void onCompleted()            {            }            @Override            public void onError(Throwable e)            {                if (callback == null)                    return;                Result r = getErrorInfo(e, url.toString(), null);                callback.onHttpResp(r);            }            @Override            public void onNext(Result r)            {                if (callback == null)                    return;                callback.onHttpResp(r);            }        });
//登录服务public interface LoginService {        @FormUrlEncoded        @POST("login_user")        Call< LoginResult> doLogin(@Field("UserName") String userName, @Field("Password") String password);    }    /**     * 用户登录     *     * @param userName     * @param password     * @param callback     */    public static void doLogin(String userName, String password, Callback<LoginResult> callback) {        ServiceManager.LoginService service = getRetrofit().create(ServiceManager.LoginService.class);        Call<LoginResult> result = service.doLogin(userName, CacheHelper.md5(password));        result.enqueue(callback);    }public static synchronized Retrofit getRetrofit() {        return new Retrofit.Builder().baseUrl(ConstantParams.BASE_URL).client(getClientInstance())                .addConverterFactory(GsonConverterFactory.create()).build();    }

四.基于Http的文件上传

File file = new File(Environment.getExternalStorageDirectory(), "a.mp4");RequestBody fileBody = RequestBody.create(MediaType.parse("application/octet-stream"), file);    RequestBody requestBody = new MultipartBody.Builder()            .setType(MultipartBody.FORM)            .addPart(Headers.of(                            "Content-Disposition",                            "form-data; name=\"username\""),                    RequestBody.create(null, "william"))            .addPart(Headers.of(                    "Content-Disposition",                    "form-data; name=\"mFile\";filename =\"wjd.mp4\""), fileBody)            .build();Request request = new Request.Builder().url("hostUrl/fileUpload")            .post(requestBody)            .build();

关于拼接上传文件的表单拼接模拟浏览器行为的方式。深度解析java http上传文件。
图片下载,文件下载;这两个一个是通过回调的Response拿到byte[]然后decode成图片;文件下载,就是拿到inputStream做写文件操作,这里就不赘述了。
注意:对于添加了retrofit之后想打印请求和返回数据的日志可以参考(评论也很重要,我项目最后采取的方法就是评论中的开源工具LoggingInterceptor)。

参考文档:http://blog.csdn.net/lmj623565791/article/details/47911083
http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2015/0106/2275.html
http://blog.csdn.net/lmj623565791/article/details/51304204#comments

1 0
原创粉丝点击