Okhttp的简单使用(kt&java)
2017-08-15 本文已影响19人
Wocus
这是一个网络请求的框架,接下来介绍如何使用,不说原理,直说怎么使用
1.依赖注入
compile 'com.squareup.okhttp:okhttp:2.4.0'
compile 'com.google.code.gson:gson:2.6.2'
2.提供一个HttpUtils的封装类
package com.wocus.myapplication.util;
import android.os.Handler;
import android.os.Looper;
import com.squareup.okhttp.Callback;
import com.squareup.okhttp.FormEncodingBuilder;
import com.squareup.okhttp.OkHttpClient;
import com.squareup.okhttp.Request;
import com.squareup.okhttp.RequestBody;
import com.squareup.okhttp.Response;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;
/**
* Created on 2017/8/15.
* Author:crs
* Description:网络请求工具类的封装
*/
public class HttpUtils {
private OkHttpClient client;
private Handler mHandler;
public HttpUtils() {
client = new OkHttpClient();
//设置连接超时时间,在网络正常的时候有效
client.setConnectTimeout(30*1000, TimeUnit.SECONDS);
//设置读取数据的超时时间
client.setReadTimeout(30*1000, TimeUnit.SECONDS);
//设置写入数据的超时时间
client.setWriteTimeout(30*1000, TimeUnit.SECONDS);
//Looper.getMainLooper() 获取主线程的消息队列
mHandler = new Handler(Looper.getMainLooper());
}
public void get(String url, BaseCallBack baseCallBack) {
Request request = buildRequest(url, null, HttpMethodType.GET);
sendRequest(request, baseCallBack);
}
public void post(String url, HashMap<String,String> params, BaseCallBack baseCallBack) {
Request request = buildRequest(url, params, HttpMethodType.POST);
sendRequest(request, baseCallBack);
}
/**
* 1)获取Request对象
*
* @param url
* @param params
* @param httpMethodType 请求方式不同,Request对象中的内容不一样
* @return Request 必须要返回Request对象, 因为发送请求的时候要用到此参数
*/
private Request buildRequest(String url, HashMap<String, String> params, HttpMethodType httpMethodType) {
//获取辅助类对象
Request.Builder builder = new Request.Builder();
builder.url(url);
//如果是get请求
if (httpMethodType == HttpMethodType.GET) {
builder.get();
} else {
RequestBody body = buildFormData(params);
builder.post(body);
}
//返回请求对象
return builder.build();
}
/**
* 2)发送网络请求
*
* @param request
* @param baseCallBack
*/
private void sendRequest(Request request, final BaseCallBack baseCallBack) {
client.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(Request request, IOException e) {
callBackFail(baseCallBack,request, e);
}
@Override
public void onResponse(Response response) throws IOException {
if (response.isSuccessful()) {
String json = response.body().string();
//此时请求结果在子线程里面,如何把结果回调到主线程里?
callBackSuccess(baseCallBack,response, json);
} else {
callBackError(baseCallBack,response, response.code());
}
}
});
}
/**
* 主要用于构建请求参数
*
* @param param
* @return ResponseBody
*/
private RequestBody buildFormData(HashMap<String,String> param) {
FormEncodingBuilder builder = new FormEncodingBuilder();
//遍历HashMap集合
if (param != null && !param.isEmpty()) {
Set<Map.Entry<String, String>> entries = param.entrySet();
for (Map.Entry<String, String> entity : entries) {
String key = entity.getKey();
String value = entity.getValue();
builder.add(key, value);
}
}
return builder.build();
}
//请求类型定义
private enum HttpMethodType {
GET,
POST
}
//定义回调接口
public interface BaseCallBack {
void onSuccess(Response response, String json);
void onFail(Request request, IOException e);
void onError(Response response, int code);
}
//主要用于子线程和主线程进行通讯
private void callBackSuccess(final BaseCallBack baseCallBack, final Response response, final String json){
mHandler.post(new Runnable() {
@Override
public void run() {
baseCallBack.onSuccess(response,json);
}
});
}
private void callBackError(final BaseCallBack baseCallBack, final Response response, final int code){
mHandler.post(new Runnable() {
@Override
public void run() {
baseCallBack.onError(response,code);
}
});
}
private void callBackFail(final BaseCallBack baseCallBack, final Request request, final IOException e){
mHandler.post(new Runnable() {
@Override
public void run() {
//相当于此run方法是在主线程执行的,可以进行更新UI的操作
baseCallBack.onFail(request,e);
}
});
}
}
3.再提供一个gson的封装类
package com.wocus.myapplication.util;
import com.google.gson.Gson;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonParser;
import com.google.gson.reflect.TypeToken;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
public class GsonUtil {
private static Gson gson = null;
static {
if (gson == null) {
gson = new Gson();
}
}
private GsonUtil() {
}
/**
* 转成json
*
* @param object
* @return
*/
public static String GsonString(Object object) {
String gsonString = null;
if (gson != null) {
gsonString = gson.toJson(object);
}
return gsonString;
}
/**
* 转成bean
*
* @param gsonString
* @param cls
* @return
*/
public static <T> T GsonToBean(String gsonString, Class<T> cls) {
T t = null;
if (gson != null) {
t = gson.fromJson(gsonString, cls);
}
return t;
}
/**
* 转成list
* 泛型在编译期类型被擦除导致报错
*
* @param gsonString
* @param cls
* @return
*/
public static <T> List<T> GsonToList(String gsonString, Class<T> cls) {
List<T> list = null;
if (gson != null) {
list = gson.fromJson(gsonString, new TypeToken<List<T>>() {
}.getType());
}
return list;
}
/**
* 转成list
* 解决泛型问题
*
* @param json
* @param cls
* @param <T>
* @return
*/
public <T> List<T> jsonToList(String json, Class<T> cls) {
Gson gson = new Gson();
List<T> list = new ArrayList<T>();
JsonArray array = new JsonParser().parse(json).getAsJsonArray();
for (final JsonElement elem : array) {
list.add(gson.fromJson(elem, cls));
}
return list;
}
/**
* 转成list中有map的
*
* @param gsonString
* @return
*/
public static <T> List<Map<String, T>> GsonToListMaps(String gsonString) {
List<Map<String, T>> list = null;
if (gson != null) {
list = gson.fromJson(gsonString,
new TypeToken<List<Map<String, T>>>() {
}.getType());
}
return list;
}
/**
* 转成map的
*
* @param gsonString
* @return
*/
public static <T> Map<String, T> GsonToMaps(String gsonString) {
Map<String, T> map = null;
if (gson != null) {
map = gson.fromJson(gsonString, new TypeToken<Map<String, T>>() {
}.getType());
}
return map;
}
}
4.请求网络使用
package com.wocus.myapplication.activity
import android.app.ProgressDialog
import android.content.Intent
import android.os.Bundle
import android.support.v7.app.AppCompatActivity
import android.util.Log
import android.view.View
import com.daimajia.androidanimations.library.Techniques
import com.daimajia.androidanimations.library.YoYo
import com.squareup.okhttp.Request
import com.squareup.okhttp.Response
import com.wocus.myapplication.R
import com.wocus.myapplication.util.GsonUtil
import com.wocus.myapplication.util.HttpUtils
import com.wocus.myapplication.util.SUtils
import es.dmoral.toasty.Toasty
import kotlinx.android.synthetic.main.activity_main.*
import java.io.IOException
/**
* 登录界面
*/
class MainActivity : AppCompatActivity(), View.OnClickListener ,HttpUtils.BaseCallBack{
var load_dialog: ProgressDialog?=null
override fun onSuccess(response: Response?, json: String?) {
Log.d("TAG","请求成功"+json)
load_dialog!!.dismiss()
var modelbean: MutableMap<String, String>? =GsonUtil.GsonToMaps<String>(json)
if (modelbean!!["code"].toString() == "1") {
startActivity(Intent(this, IndexActivity::class.java))
Toasty.success(this, "登录成功").show()
}else{
Toasty.error(this,modelbean.get("msg").toString())
}
}
override fun onFail(request: Request?, e: IOException?) {
load_dialog!!.dismiss()
Toasty.error(this,"网络连接超时").show()
}
override fun onError(response: Response?, code: Int) {
load_dialog!!.dismiss()
Toasty.error(this, "服务器发生错误").show()
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
btn_login_login.setOnClickListener(this)
load_dialog=SUtils().initDialog(this)
}
override fun onClick(v: View?) {
when(v?.id){
R.id.btn_login_login->
if(edt_login_account.text.trim().length<=0){
Toasty.info(this,"请输入账号").show()
YoYo.with(Techniques.Tada).duration(500).playOn(layout_login_account)
return
}else if(edt_login_password.text.trim().length<=0){
Toasty.info(this,"请输入密码").show()
YoYo.with(Techniques.Tada).duration(500).playOn(layout_login_pwd)
return
}else{
load_dialog!!.show()
startActivity(Intent(this, IndexActivity::class.java))
var map:HashMap<String,String>?= HashMap()
map!!.put("account",edt_login_account.text.toString())
map.put("password",edt_login_account.text.toString())
HttpUtils().post("http://192.168.0.117:8080/Shopnert/login.do",map,this)
}
}
}
}
请求网络就到这里,接下来使用okhttp实现下载,提供一个okhttp下载封装工具类
package com.wocus.myapplication.util;
import android.os.Environment;
import android.support.annotation.NonNull;
import com.squareup.okhttp.Callback;
import com.squareup.okhttp.OkHttpClient;
import com.squareup.okhttp.Request;
import com.squareup.okhttp.Response;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
public class DownloadUtil {
private static DownloadUtil downloadUtil;
private final OkHttpClient okHttpClient;
public static DownloadUtil get() {
if (downloadUtil == null) {
downloadUtil = new DownloadUtil();
}
return downloadUtil;
}
private DownloadUtil() {
okHttpClient = new OkHttpClient();
}
/**
* @param url 下载连接
* @param saveDir 储存下载文件的SDCard目录
* @param listener 下载监听
*/
public void download(final String url, final String saveDir, final OnDownloadListener listener) {
Request request = new Request.Builder().url(url).build();
okHttpClient.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(Request request, IOException e) {
listener.onDownloadFailed();
}
@Override
public void onResponse(Response response) throws IOException {
InputStream is = null;
byte[] buf = new byte[2048];
int len = 0;
FileOutputStream fos = null;
// 储存下载文件的目录
String savePath = isExistDir(saveDir);
try {
is = response.body().byteStream();
long total = response.body().contentLength();
File file = new File(savePath, getNameFromUrl(url));
fos = new FileOutputStream(file);
long sum = 0;
while ((len = is.read(buf)) != -1) {
fos.write(buf, 0, len);
sum += len;
int progress = (int) (sum * 1.0f / total * 100);
// 下载中
listener.onDownloading(progress);
}
fos.flush();
// 下载完成
listener.onDownloadSuccess();
} catch (Exception e) {
listener.onDownloadFailed();
} finally {
try {
if (is != null)
is.close();
} catch (IOException e) {
}
try {
if (fos != null)
fos.close();
} catch (IOException e) {
}
}
}
});
}
/**
* @param saveDir
* @return
* @throws IOException
* 判断下载目录是否存在
*/
private String isExistDir(String saveDir) throws IOException {
// 下载位置
File downloadFile = new File(Environment.getExternalStorageDirectory(), saveDir);
if (!downloadFile.mkdirs()) {
downloadFile.createNewFile();
}
String savePath = downloadFile.getAbsolutePath();
return savePath;
}
/**
* @param url
* @return
* 从下载连接中解析出文件名
*/
@NonNull
private String getNameFromUrl(String url) {
return url.substring(url.lastIndexOf("/") + 1);
}
public interface OnDownloadListener {
/**
* 下载成功
*/
void onDownloadSuccess();
/**
* @param progress
* 下载进度
*/
void onDownloading(int progress);
/**
* 下载失败
*/
void onDownloadFailed();
}
}
下载封装类的使用
DownloadUtil.get().download("http://192.168.0.117:8080/Shopnert/ShipCargo.apk", "download", new DownloadUtil.OnDownloadListener() {
@Override
public void onDownloadSuccess() {
Toasty.error(getBaseContext(), "下载成功").show();
}
@Override
public void onDownloading(int progress) {
Toasty.error(getBaseContext(), "进度为" + progress).show();
}
@Override
public void onDownloadFailed() {
Toasty.error(getBaseContext(), "下载失败").show();
}
});
简单使用就到这里。