Okhttp3基本用法详解

2,477 阅读2分钟

校科创项目即将接近尾声,最近学习了一下安卓客户端和服务端的对接,使用的是Okhttp这个开源框架。

1 Okhttp简介

Okhttp是目前Android主流的处理网络请求的开源框架,用于替代HttpUrlConnection。从Android4.4开始,google已经开始将源码中的HttpURLConnection替换为OkHttp。

2 Okhttp的安装

在所处Module的build.gradle的dependencies中添加:

implementation("com.squareup.okhttp3:okhttp:4.3.1")

添加后同步。

3 Okhttp使用的基本步骤

  • 取得 OkHttpClient 对象(或OkHttpClient.Builder对象)

    OkHttpClient okHttpClient=new OkHttpClient();
    /*或*/
    OkHttpClient.Builder okHttpClientBuilder=new OkHttpClient.Builder();
    
  • 构造Request

    Request.Builder builder=new Request.Builder();
    /*****get请求-请求头URL*****/
    Request request=builder.get().url(mBaseUrl+"请求内容").build();
    
    /*****post请求-请求体*****/
    RequestBody requestBody=RequestBody.create(MediaType.parse("text/plain;charset=utf-8"), "json数据内容");
    /*或*/
    RequestBody requestBody = RequestBody.create(MediaType.parse("application/octet-stream"), file);
    /*或*/
    FormBody requestBody = new FormBody  //FormBody extends RequestBody
                    .Builder()
                    .add("usename","zqq_post")
                    .add("password","123456").build();
    
    Request request = builder.url(mBaseUrl + 服务端方法名).post(requestBody).build();
    
  • 将Request封装为Call

    private void executeRequest(Request request) throws IOException {
        Call call=okHttpClientBuilder.build().newCall(request);
        call.enqueue(new Callback() {
            @Override
            public void onFailure(@NotNull Call call, @NotNull IOException e) {
                L.e("onFailure" +e.getMessage());
                e.printStackTrace();
            }
    
            @Override
            public void onResponse(@NotNull Call call, @NotNull Response response) throws IOException {
                L.e("onResponse:");
                final String res=response.body().string();
                L.e(res);
                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                       /******对客户端元素的操作******/
                    }
                });
            }
        });
    }
    
  • 执行call

    executeRequest(request);
    

4 Session和Cookie

  • 功能:记录一系列状态

  • 两者区别:session是记录在服务端的,cookie是记录在客户端的

  • session解决了不同HTTP的请求的关联问题,让它们产生联系

  • session追踪的实现

    在客户端中,我需要为赋予cookiejar

    okHttpClientBuilder.cookieJar(new PersistenceCookieJar());
    

​ 封装的接口如下:

public class PersistenceCookieJar implements CookieJar {
    List<Cookie> cache = new ArrayList<>();
    //Http请求结束,Response中有Cookie时候回调
    @Override
    public void saveFromResponse(HttpUrl url, List<Cookie> cookies) {
        //内存中缓存Cookie
        cache.addAll(cookies);
    }
    //Http发送请求前回调,Request中设置Cookie
    @Override
    public List<Cookie> loadForRequest(HttpUrl url) {
        //过期的Cookie
        List<Cookie> invalidCookies = new ArrayList<>();
        //有效的Cookie
        List<Cookie> validCookies = new ArrayList<>();

        for (Cookie cookie : cache) {

            if (cookie.expiresAt() < System.currentTimeMillis()) {
                //判断是否过期
                invalidCookies.add(cookie);
            } else if (cookie.matches(url)) {
                //匹配Cookie对应url
                validCookies.add(cookie);
            }
        }
        //缓存中移除过期的Cookie
        cache.removeAll(invalidCookies);
        //返回List<Cookie>让Request进行设置
        return validCookies;
    }
};

同时,在服务端中,我可以获取到相应的sessionId:

request.getSession.getId();

5 常见问题

  • Android 6.0+的动态权限问题

除了要在AndroidManifest中声明权限,还要使用如下代码动态获取

public void accessPermission(){
        if (Build.VERSION.SDK_INT >= 23) {
            int REQUEST_CODE_CONTACT = 101;
            String[] permissions = {Manifest.permission.WRITE_EXTERNAL_STORAGE};
            //验证是否许可权限
            for (String str : permissions) {
                if (this.checkSelfPermission(str) != PackageManager.PERMISSION_GRANTED) {
                    //申请权限
                    this.requestPermissions(permissions, REQUEST_CODE_CONTACT);
                    return;
                }}}}