一、简介
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/51778793OKHttp的功能:
- 联网请求文本数据
- 大文件下载
- 大文件上传
- 请求图片
二、添加依赖
compile 'com.squareup.okhttp3:okhttp:3.7.0'
三、解锁技能
<1> 使用原生OKHttp的Get请求
-
添加网络权限;
-
使用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(); }
-
开辟子线程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;
-
通过handler更新ui,显示请求结果。
case GET: mTextView2.setText((String) msg.obj); break;
<2> 使用原生OKHttp的Post请求
-
官网示例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(); }
-
开辟子线程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,很麻烦,需要我们想法设法可以再次封装,方便我们的使用。
鸿洋博客地址:http://blog.csdn.net/lmj623565791/article/details/49734867/;
添加依赖:compile 'com.zhy:okhttputils:2.6.2';
-
使用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; } } }); }
-
使用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; } } };
-
下载文件,添加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); }
-
文件上传;
文件服务器搭建:下载链接,我的测试链接: 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); } -
请求图片;
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的强项)
-
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); } } -
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); } } } -
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; } } }
四、栗子效果
演示视频
五、栗子下载
下载地址