Android OKHttp

自学了视频的内容,整理成笔记,方便查阅和复习。

简介

OKHttp是一款高效的HTTP客户端,支持连接同一地址的链接共享同一个socket,通过连接池来减小响应延迟,还有透明的GZIP压缩,请求缓存等优势,其核心主要有路由、连接协议、拦截器、代理、安全性认证、连接池以及网络适配,拦截器主要是指添加,移除或者转换请求或者回应的头部信息。这个库也是square开源的一个网络请求库(okhttp内部依赖okio)。

下载地址:http://square.github.io/okhttp/

1、可在上面下载 :
在这里插入图片描述
2、或在build.gradle中添加:

compile 'com.squareup.okhttp3:okhttp:3.4.1'

在AndroidManifest.xml文件添加网络访问:

<uses-permission android:name="android.permission.INTERNET"/>

OkHttp主要功能:
1、联网请求文本数据
2、大文件下载
3、大文件上传
4、请求图片

首先写好布局和代码:
布局:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.atguigu.android.atguigu.activity.OkhttpAcyivity"
    android:orientation="vertical">

    <Button
        android:id="@+id/get"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="get请求"/>

    <Button
        android:id="@+id/post"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="post请求"/>

    <Button
        android:id="@+id/get_utils"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="get_utils请求"/>

    <Button
        android:id="@+id/post_utils"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="post_utils请求"/>

    <Button
        android:id="@+id/downloadfile"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="使用post_utils下载文件"/>

    <Button
        android:id="@+id/uploadfile"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="使用post_utils上传文件"/>


    <Button
        android:id="@+id/getimage"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="使用post_utils请求单张图片"/>


    <ProgressBar
        android:id="@+id/pb"
        style="?android:progressBarStyleHorizontal"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />

    <ImageView
        android:id="@+id/image"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        />

    <TextView
        android:id="@+id/text"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:text="显示数据"
        android:textSize="20sp"
        />

</LinearLayout>

点击事件:

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.okhttp_acyivity);
        get = (Button)findViewById(R.id.get);
        text = (TextView) findViewById(R.id.text);
        post = (Button)findViewById(R.id.post);
        get_utils = (Button)findViewById(R.id.get_utils);
        post_utils = (Button)findViewById(R.id.post_utils);
        downloadfile = (Button)findViewById(R.id.downloadfile);
        pb = (ProgressBar)findViewById(R.id.pb);
        uploadfile = (Button)findViewById(R.id.uploadfile);
        getimage = (Button)findViewById(R.id.getimage);
        image = (ImageView)findViewById(R.id.image);

        get.setOnClickListener(this);
        post.setOnClickListener(this);
        get_utils.setOnClickListener(this);
        post_utils.setOnClickListener(this);
        downloadfile.setOnClickListener(this);
        uploadfile.setOnClickListener(this);
        getimage.setOnClickListener(this);

    }

    @Override
    public void onClick(View v) {
        switch (v.getId()){
            case R.id.get://get请求
                //分线程
                new Thread(){
                    @Override
                    public void run() {
                        super.run();
                        //获取数据
                        getDataFronGet();
                    }
                }.start();
                break;

            case R.id.post://post请求
                //分线程
                new Thread(){
                    @Override
                    public void run() {
                        super.run();
                        //获取数据
                        getDataFronPost();
                    }
                }.start();
                break;

            case R.id.get_utils://使用okhttp-utils get请求
                getDataByOkhttputils();
                break;

            case R.id.post_utils:
                postDataByOkhttputils();//使用okhttp-utils post请求
                break;

            case R.id.downloadfile://使用okhttp-utils 下载文件
                downloadFile();
                break;

            case R.id.uploadfile://使用okhttp-utils 上传文件
                multiFileUpload();
                break;

            case R.id.getimage://请求单张图片
                image();
                break;
        }
    }

GET请求

在这里插入图片描述
使用get请求网络数据:

    private void getDataFronGet() {
        try {
            String result = get("http://api.m.mtime.cn/PageSubArea/TrailerList.api");
            Log.w(TAG,result);
            Message msg = Message.obtain();
            msg.what = GET;
            msg.obj = result;
            //主线程更新数UI
            handler.sendMessage(msg);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

get请求:

    OkHttpClient client = new OkHttpClient();
    private String get(String url) throws IOException {
        Request request = new Request.Builder()
                .url(url)
                .build();
        Response response = client.newCall(request).execute();
        return response.body().string();
    }

POST请求

在这里插入图片描述
使用post请求网络数据:

    private void getDataFronPost() {
        try {
            String result = post("http://api.m.mtime.cn/PageSubArea/TrailerList.api","");
            Log.w(TAG,result);
            Message msg = Message.obtain();
            msg.what = POST;
            msg.obj = result;
            //主线程更新数UI
            handler.sendMessage(msg);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

post请求:

    private String post(String url,String json) throws IOException {
        RequestBody body = RequestBody.create(JSON,json);
        Request request = new Request.Builder()
                .url(url)
                .post(body)
                .build();
        Response response = client.newCall(request).execute();
        return response.body().string();
    }

更新UI,显示文本:

    private Handler handler  = new Handler(){
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            switch (msg.what){
                case GET:
                    text.setText((String)msg.obj);
                    
                case POST:
                    text.setText("");
                    text.setText((String)msg.obj);
                    break;
            }
        }
    };

OKHttp_Utils 简介

下载:https://github.com/hongyangAndroid/okhttp-utils

import Module
运行后会出现一些错误,解决报错:
1、在okhttp-utils的build.gradle文件中注射掉一下代码

//apply plugin: 'com.novoda.bintray-release'//添加
添加
//publish {
//    userOrg = 'hongyangandroid'//bintray.com用户名
//    groupId = 'com.zhy'//jcenter上的路径
//    artifactId = 'okhttputils'//项目名称
//    publishVersion = '2.6.2'//版本号
//    desc = 'Oh hi, this is a nice description for a project, right?'
//    website = 'https://github.com/hongyangAndroid/okhttp-utils'
//}
//

2、在sample-okhttp中的build.gradle文件中配置:

allprojects {
    repositories {
        maven { url "https://jitpack.io" }
    }
}

把okhttp-utils集成到我们项目中
右键app --> Open Module Settings -->Dependencies -->右边+号 -->选择Module dependency -->选择okhttp-utils

解决报错:
1、在我们的项目的build.gradle文件中关联库

implementation project(':okhttputils')

2、因为okhttputils库里面本身就有okhttp库和okio库,需要在我们项目的build.gradle文件中注释掉以下代码

//    implementation files('libs/okhttp-3.4.1.jar')
//    implementation files('libs/okio-1.9.0.jar')

OKHttp 使用 Utils 的 GET 请求文本

    public void getDataByOkhttputils()
    {
        String url = "http://www.zhiyun-tech.com/App/Rider-M/changelog-zh.txt";
        url="http://api.m.mtime.cn/PageSubArea/TrailerList.api";
        OkHttpUtils.get()
                .url(url)
                .id(100)
                .build()
                .execute(new MyStringCallback());
    }
    public class MyStringCallback extends StringCallback
    {
        @Override
        public void onBefore(Request request, int id)
        {
            setTitle("loading...");
        }

        @Override
        public void onAfter(int id)
        {
            setTitle("Sample-okHttp");
        }

        @Override
        public void onError(Call call, Exception e, int id)
        {
            e.printStackTrace();
            text.setText("onError:" + e.getMessage());
        }

        @Override
        public void onResponse(String response, int id)
        {
            Log.e(TAG, "onResponse:complete");
            text.setText("onResponse:" + response);

            switch (id)
            {
                case 100:
                    Toast.makeText(OkhttpAcyivity.this, "http", Toast.LENGTH_SHORT).show();
                    break;
                case 101:
                    Toast.makeText(OkhttpAcyivity.this, "https", Toast.LENGTH_SHORT).show();
                    break;
            }
        }

        @Override
        public void inProgress(float progress, long total, int id)
        {
            Log.e(TAG, "inProgress:" + progress);
//            mProgressBar.setProgress((int) (100 * progress));
        }
    }

OKHttp 使用 Utils 的 POST 请求文本

    public void postDataByOkhttputils()
    {
        String url = "http://www.zhiyun-tech.com/App/Rider-M/changelog-zh.txt";
        url="http://api.m.mtime.cn/PageSubArea/TrailerList.api";
        OkHttpUtils
                .post()
                .url(url)
                .id(100)
                .build()
                .execute(new MyStringCallback());
    }

OKHttp 使用 Utils下载大文件

    public void downloadFile()
    {
        String url = "http://vfx.mtime.cn/Video/2016/07/24/mp4/160724154733643806.mp4";
        OkHttpUtils//
                .get()//
                .url(url)//
                .build()//
                .execute(new FileCallBack(Environment.getExternalStorageDirectory().getAbsolutePath(), "test.mp4")//
                {

                    @Override
                    public void onBefore(Request request, int id)
                    {
                    }

                    @Override
                    public void inProgress(float progress, long total, int id)
                    {
                        pb.setProgress((int) (100 * progress));
                        Log.e(TAG, "inProgress :" + (int) (100 * progress));
                    }

                    @Override
                    public void onError(Call call, Exception e, int id)
                    {
                        Log.e(TAG, "onError :" + e.getMessage());
                    }

                    @Override
                    public void onResponse(File file, int id)
                    {
                        Log.e(TAG, "onResponse :" + file.getAbsolutePath());
                    }
                });
    }

在手机上播放:
在这里插入图片描述

OKHttp 使用 Utils 进行文件的上传

搭好服务器之后,上传文件

    public void multiFileUpload()
    {
        String mBaseUrl = "http://192.168.35.11:8080/FileUpload/FileUploadServlet";
        File file = new File(Environment.getExternalStorageDirectory(), "a.png");
        File file2 = new File(Environment.getExternalStorageDirectory(), "c.png");
        if (!file.exists())
        {
            Toast.makeText(OkhttpAcyivity.this, "文件不存在,请修改文件路径", Toast.LENGTH_SHORT).show();
            return;
        }
        Map<String, String> params = new HashMap<>();
        params.put("username", "张鸿洋");
        params.put("password", "123");

        String url = mBaseUrl;
        OkHttpUtils.post()//
                .addFile("mFile", "aa.png", file)//
                .addFile("mFile", "cc.png", file2)//
                .url(url)
                .params(params)//
                .build()//
                .execute(new MyStringCallback());
    }

OKHttp 使用 Utils 请求单张图片

    public void image()
    {
        text.setText("");
        String url = "http://images.csdn.net/20150817/1.jpg";
        OkHttpUtils
                .get()//
                .url(url)//
                .tag(this)//
                .build()//
                .connTimeOut(20000)
                .readTimeOut(20000)
                .writeTimeOut(20000)
                .execute(new BitmapCallback()
                {
                    @Override
                    public void onError(Call call, Exception e, int id)
                    {
                        text.setText("onError:" + e.getMessage());
                    }

                    @Override
                    public void onResponse(Bitmap bitmap, int id)
                    {
                        Log.e("TAG", "onResponse:complete");
                        image.setImageBitmap(bitmap);
                    }
                });
    }

在这里插入图片描述

OKHttp 其他封装库

封装了okhttp的网络框架,支持大文件上传下载,上传进度回调,下载进度回调,表单上传(多文件和多参数一起上传),链式调用,可以自定义返 回对象,支持Https和自签名证书,支持cookie自动管理,支持四种缓存模式缓存网络数据,支持301、302重定向,扩展了统一的上传管理和下载管理功能。

下载连接:https://github.com/jeasonlzy/okhttp-OkGo

OKHttp 源码分析

一、应用层:
1、 将请求添加到分发器中 client.dispatcher().executed(this);
2、 创建截获器 ApplicationInterceptorChain(对请求进行压缩、修改编码等处理)

二、逻辑层
1、数据缓存:
发送请求sendRequest()之前对数据进行缓存处理。
(1)缓存的数据没有过期,直接使用
(2)缓存的数据过期,先用过期的,然后再去网络请求数据,并更新本地数据
(3)缓存的数据没有,去网络直接获取

2、底层使用连接池
连接 connect() --> 创建一个流newStream() --> 找到一个好的连接findHealthyConnection() --> 在线程池中查找好的连接findConnection() --> 连接池connectPool --> 发现连接池中有可用的连接 pooledConnection

3、路线选择器
如果连接池中没有可用的,先从路径选择(routeSelector)中查找 --> 如果在路线选择器没有找到 --> 创建新的连接newConnection

4、网络截获器可以有多个
读取答复 readResponse() --> 创建网络截获器NetworkInterceptorChain(),递归实现 --> 应答 engine.getResponse() --> 没有重定向直接返回 --> 如果有重定向,再次创建截获器 --> 截获器可以有多个,取决于是否有重定向

三、链路层
1、底层是 socket
连接connectSocket() --> 拿source 读数据 --> 拿sink写数据
在这里插入图片描述
根据用户的请求Request放入到指定队列,并使用拦截器链的方式去执行我们的请求操作。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值