Android框架之路——OKHttp的使用

一、简介

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

这个库也是square开源的一个网络请求库(okhttp内部依赖okio),现在已被Google使用在Android源码上。

官网地址:http://square.github.io/okhttp/
Github Wiki:https://github.com/square/okhttp/wiki
Wiki 翻译:http://blog.csdn.net/jackingzheng/article/details/51778793

OKHttp的功能:

  • 联网请求文本数据
  • 大文件下载
  • 大文件上传
  • 请求图片

二、添加依赖

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

三、解锁技能

<1> 使用原生OKHttp的Get请求

  1. 添加网络权限;

    
    
  2. 使用http://square.github.io/okhttp/中示例get方法,该方法请求url地址只能在子线程中运行;

    /**
     * get请求,要求在子线程运行
     * @param url
     * @return
     * @throws IOException
     */
    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();
    }
    
  3. 开辟子线程get方式请求数据;

    case R.id.button:
           new Thread(){
               @Override
               public void run() {
                   super.run();
                   try {
                       String result = get("http://gank.io/api/data/Android/2/1");
                       Message msg = Message.obtain();
                       msg.what = GET;
                       msg.obj = result;
                       mHandler.sendMessage(msg);
                   } catch (IOException e) {
                       e.printStackTrace();
                   }
               }
           }.start();
           break;
    
  4. 通过handler更新ui,显示请求结果。

    case GET:
       mTextView2.setText((String) msg.obj);
       break;
    

<2> 使用原生OKHttp的Post请求

  1. 官网示例post方法,也需要在子线程中运行;

    /**
     * post请求
     * @param url
     * @param json 上传时需要json
     * @return
     * @throws IOException
     */
    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();
    }
    
  2. 开辟子线程psot请求数据;

    new Thread(){
        @Override
        public void run() {
            super.run();
            try {
                String result = post("http://api.m.mtime.cn/PageSubArea/TrailerList.api", null);
                Message msg = Message.obtain();
                msg.what = POST;
                msg.obj = result;
                mHandler.sendMessage(msg);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }.start();
    

<3> 使用第三方封装的OKHttp库okhttp-utils(鸿洋大神出品)

我们使用原生的OKHttp时,需要自己去开辟子线程请求网络数据,然后通过Handler去更新UI,很麻烦,需要我们想法设法可以再次封装,方便我们的使用。

  1. 鸿洋博客地址:http://blog.csdn.net/lmj623565791/article/details/49734867/;
  2. 添加依赖:compile ‘com.zhy:okhttputils:2.6.2’;
  3. 使用OkhttpUtils进行get请求;

    /**
     * 使用OkhttpUtils进行get请求
     * @param url url地址
     * @param id 请求ID号
     */
    private void getByOkhttpUtils(String url, int id) {
        OkHttpUtils.get().url(url).id(id).build().execute(new StringCallback() {
            @Override
            public void onError(Call call, Exception e, int id) {
                e.printStackTrace();
                mTextView2.setText(e.getMessage());
            }
    
            @Override
            public void onResponse(String response, int id) {
                mTextView2.setText(response);
                switch (id){
                    case 100:
                        Toast.makeText(getApplicationContext(), "100请求成功", Toast.LENGTH_SHORT).show();
                        break;
                }
            }
        });
    }    
    
  4. 使用OkhttpUtils进行post请求;

    /**
     * 使用OkhttpUtils进行post请求
     * @param url
     * @param id
     */
    private void postByOkhttpUtils(String url, int id) {
        OkHttpUtils.post().url(url).id(id).build().execute(mStringCallback);
    }
    
    ........
    
    //封装回调
    private StringCallback mStringCallback = new StringCallback() {
        @Override
        public void onError(Call call, Exception e, int id) {
            e.printStackTrace();
            mTextView2.setText(e.getMessage());
        }
    
        @Override
        public void onResponse(String response, int id) {
            mTextView2.setText(response);
            switch (id) {
                case 100:
                    Toast.makeText(getApplicationContext(), "100get请求成功", Toast.LENGTH_SHORT).show();
                    break;
                case 101:
                    Toast.makeText(getApplicationContext(), "101post请求成功", Toast.LENGTH_SHORT).show();
                    break;
            }
        }
    };   
    
  5. 下载文件,添加WRITE_EXTERNAL_STORAGE权限,设置回调并进行下载;

    //参数包含保存路径和保存文件名
    private FileCallBack mFileCallBack = new FileCallBack(Environment.getExternalStorageDirectory().getAbsolutePath(), "test.mp4") {
            @Override
            public void onError(Call call, Exception e, int id) {
                e.printStackTrace();
                mTextView2.setText(e.getMessage());
            }
    
        @Override
        public void inProgress(float progress, long total, int id) {
            super.inProgress(progress, total, id);
            mProgressBar.setProgress((int) (100 * progress));
            mTextView2.setText("下载进度:" + (int) (100 * progress) + "/%");
        }
    
        @Override
        public void onResponse(File response, int id) {
        }
    };
    
    ......
    
    /**
     * 使用OkhttpUtils进行下载大文件
     * @param url
     */
    private void downloadFileByOkhttpUtils(String url){
        OkHttpUtils.get().url(url).build().execute(mFileCallBack);
    }
    
  6. 文件上传;
    文件服务器搭建:下载链接,我的测试链接: http://192.168.1.102/FileUpload/index.jsp;

    /**
     * 单文件或多文件上传
     * @param url url地址
     * @param id 请求id
     * @param username 用户名参数
     * @param files 文件集合
     */
    private void uploadFilesByOkhttpUtils(String url, int id, String username, List files) {
        for (File file : files) {
            if (!file.exists()) {
                Toast.makeText(getApplicationContext(), "文件" + file.getName() + "不存在", Toast.LENGTH_SHORT).show();
                return;
            }
        }
        Map params = new HashMap<>();
        params.put("username", username);
    
        PostFormBuilder builder = OkHttpUtils.post();
        for (File file : files) {
            builder = builder.addFile(username, "server" + file.getName(), file);
        }
        builder.url(url).id(id).params(params).build().execute(mStringCallback);
    
    }
    
    ......
    
    @OnClick(R.id.button3)
    public void onViewClicked() {
        List files = new ArrayList<>();
        files.add(new File(Environment.getExternalStorageDirectory().getAbsolutePath(), "QQ_8.9.2.20760_setup.exe"));
        files.add(new File(Environment.getExternalStorageDirectory().getAbsolutePath(), "test.mp4"));
        uploadFilesByOkhttpUtils("http://192.168.1.102/FileUpload/FileUploadServlet", 102, "Mr.sorrow", files);
    }
    
  7. 请求图片;

    private BitmapCallback mBitmapCallback = new BitmapCallback() {
        @Override
        public void onError(Call call, Exception e, int id) {
            e.printStackTrace();
            mTextView2.setText(e.getMessage());
        }
    
        @Override
        public void onResponse(Bitmap response, int id) {
            mImageView.setImageBitmap(response);
        }
    };      
    
    .......
    
    /**
     * 请求单张图片
     * @param url
     * @param id
     */
    private void getPicByOkhttpUtils(String url, int id) {
        OkHttpUtils
                .get()
                .url(url)
                .tag(this)
                .id(id)
                .build()
                .connTimeOut(20000)    //设置连接超时、读取超时、写入超时
                .readTimeOut(20000)
                .writeTimeOut(20000)
                .execute(mBitmapCallback);
    }
    

<4> 加载图片集合(并不是okhttp-utils的强项)

  1. Activity:

    public class ThirdActivity extends AppCompatActivity {
    
        private List picsUrl;
    
        @BindView(R.id.listview)
        ListView mListview;
        @BindView(R.id.progressBar)
        ProgressBar mProgressBar;
        @BindView(R.id.textView)
        TextView mTextView;
    
        private StringCallback mStringCallback = new StringCallback() {
            @Override
            public void onError(Call call, Exception e, int id) {
                e.printStackTrace();
                mTextView.setVisibility(View.VISIBLE);
                mProgressBar.setVisibility(View.GONE);
            }
    
            @Override
            public void onResponse(String response, int id) {
                mTextView.setVisibility(View.GONE);
                switch (id) {
                    case 100:
                        Toast.makeText(getApplicationContext(), "请求成功", Toast.LENGTH_SHORT).show();
                        break;
                }
                if (response != null) {
                    Meizi meizi1 = processData(response);
                    if (meizi1 != null) {
                        List beanList = meizi1.getResults();
                        if (!beanList.isEmpty()) {
                            for (Meizi.ResultsBean resultsBean : beanList) {
                                picsUrl.add(resultsBean.getUrl());
                                Log.i("xxxxx", resultsBean.getUrl());
                            }
                        }
                    }
                }
    
                mListview.setAdapter(new MyAdapter(picsUrl, ThirdActivity.this));
    
                mProgressBar.setVisibility(View.GONE);
            }
    
            @Override
            public void inProgress(float progress, long total, int id) {
                super.inProgress(progress, total, id);
            }
        };
    
        /**
         * 解析json数据
         *
         * @param json
         */
        private Meizi processData(String json) {
            Gson gson = new Gson();
            return gson.fromJson(json, Meizi.class);
        }
    
        @Override
        protected void onCreate(@Nullable Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_third);
            ButterKnife.bind(this);
            picsUrl = new ArrayList<>();
            getDataByOkhttpUtils("http://gank.io/api/data/%E7%A6%8F%E5%88%A9/20/1", 100);
        }
    
        /**
         * get请求json数据
         *
         * @param url
         * @param id
         */
        private void getDataByOkhttpUtils(String url, int id) {
            OkHttpUtils.get().url(url).id(id).build().execute(mStringCallback);
        }
    }
    
  2. Adapter:

    public class MyAdapter extends BaseAdapter {
    
        private List data;
        private Context mContext;
    
        public MyAdapter(List data, Context context) {
            this.data = data;
            mContext = context;
        }
    
        @Override
        public int getCount() {
            return data.size();
        }
    
        @Override
        public String getItem(int position) {
            return data.get(position);
        }
    
        @Override
        public long getItemId(int position) {
            return position;
        }
    
        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            ViewHolder holder = null;
            if (convertView == null) {
                convertView = View.inflate(mContext, R.layout.items, null);
                holder = new ViewHolder(convertView);
                convertView.setTag(holder);
            } else {
                holder = (ViewHolder) convertView.getTag();
            }
    
            holder.mTvName.setText(getItem(position));
            holder.mTvDesc.setText(getItem(position));
    
            final ViewHolder finalHolder = holder;
            OkHttpUtils
                    .get()
                    .url(getItem(position))
                    .tag(this)
                    .build()
                    .connTimeOut(20000)    //设置连接超时、读取超时、写入超时
                    .readTimeOut(20000)
                    .writeTimeOut(20000)
                    .execute(new BitmapCallback() {
                        @Override
                        public void onError(Call call, Exception e, int id) {
    
                        }
    
                        @Override
                        public void onResponse(Bitmap response, int id) {
                            finalHolder.mIvIcon.setImageBitmap(response);
                        }
                    });
            return convertView;
        }
    
        static class ViewHolder {
            @BindView(R.id.iv_icon)
            ImageView mIvIcon;
            @BindView(R.id.tv_name)
            TextView mTvName;
            @BindView(R.id.tv_desc)
            TextView mTvDesc;
    
            ViewHolder(View view) {
                ButterKnife.bind(this, view);
            }
        }
    }
    
  3. GsonFormat生成的实体Bean:

    public class Meizi {
        private boolean error;
        private List results;
    
        public boolean isError() {
            return error;
        }
    
        public void setError(boolean error) {
            this.error = error;
        }
    
        public List getResults() {
            return results;
        }
    
        public void setResults(List results) {
            this.results = results;
        }
    
        public static class ResultsBean {
            private String _id;
            private String createdAt;
            private String desc;
            private String publishedAt;
            private String source;
            private String type;
            private String url;
            private boolean used;
            private String who;
    
            public String get_id() {
                return _id;
            }
    
            public void set_id(String _id) {
                this._id = _id;
            }
    
            public String getCreatedAt() {
                return createdAt;
            }
    
            public void setCreatedAt(String createdAt) {
                this.createdAt = createdAt;
            }
    
            public String getDesc() {
                return desc;
            }
    
            public void setDesc(String desc) {
                this.desc = desc;
            }
    
            public String getPublishedAt() {
                return publishedAt;
            }
    
            public void setPublishedAt(String publishedAt) {
                this.publishedAt = publishedAt;
            }
    
            public String getSource() {
                return source;
            }
    
            public void setSource(String source) {
                this.source = source;
            }
    
            public String getType() {
                return type;
            }
    
            public void setType(String type) {
                this.type = type;
            }
    
            public String getUrl() {
                return url;
            }
    
            public void setUrl(String url) {
                this.url = url;
            }
    
            public boolean isUsed() {
                return used;
            }
    
            public void setUsed(boolean used) {
                this.used = used;
            }
    
            public String getWho() {
                return who;
            }
    
            public void setWho(String who) {
                this.who = who;
            }
        }
    }
    

四、栗子效果

       演示视频

五、栗子下载

       下载地址



个人公众号:每日推荐一篇技术博客,坚持每日进步一丢丢…欢迎关注,想建个微信群,主要讨论安卓和Java语言,一起打基础、用框架、学设计模式,菜鸡变菜鸟,菜鸟再起飞,愿意一起努力的话可以公众号留言,谢谢…

20170530210352492

你可能感兴趣的:(Android,Android框架之路)