Ion 异步网络请求和图片加载类库
概述:
所有网络库的原理是: 网络请求一般是基于HttpURLConnection和HttpClient进行封装的,也有自己编写Socket实现的,比如ion和OkHttp;请求的执行一般是通过线程池来管理,异步请求得到结果,则通过回调接口接收;并且一般接收结果的回调都通过Handler去在主线程执行
介绍:
它支持网络请求和进行图片加载的双重功能
拥有链式api风格(Fluent API)
当Activity结束的时候支持自动的取消操作
支持SPDY/HTTP2,缓存,Gzip压缩,HTTP连接的重用等
并且是基于AndroidAsync实现的,AndroidAsync是作者的另一个使用socket实现的,遵循http协议的类库
注意:
①:ION默认的大部分请求都是POST
②:回调的参数是根据asXXX来决定的,回调用有个Exception,如果不为null,那么代表请求失败
③:ION本身就是单例,不需要再次封装,链式编程调用即可
④:回调是可以自定义类型的:
public static class Tweet { //自定义的类型 public String id; public String text; public String photo; } public void getTweets() throws Exception { Ion.with(context) .load("http://example.com/api/tweets") .as(new TypeToken<List<Tweet>>(){}) .setCallback(new FutureCallback<List<Tweet>>() { @Override public void onCompleted(Exception e, List<Tweet> tweets) { // chirp chirp } }); }
⑤:第6:封装了常用的Utils,如果有些功能没涉及到可以查看github中的ion 或 ion-sample
1.查看源码Sample:
github下载ZIP:https://github.com/koush/ion#get-ion
解压后:将Sample以import Module的形式导入即可
2:使用
项目的build.gradle添加依赖:compile 'com.koushikdutta.ion:ion:2.+'
3.使用方式:
首先需要Ion.with,然后使用链式编程,调用想调用的功能:
设置请求头
设置请求参数
上传文件(图片,gif,文件)
下载文件
设置回调
从本地获取文件
4.常用方法:
请求类型url/文件
load(String uri)//请求一个 url,默认是以GET的方式进行请求
load(String method, String url)//指定请求方式(GET 或 POST)
load(File file) //请求一个文件(从文件中加载数据,例如Assets或sdcard)
请求头
setLogging(String tag, int level)//给当前请求添加log 并可以指定tag和 level
setHeader(String name, String value)//设置请求头
setHeader(Map<String , String>)//设置请求头
addHeader(String name, String value)//添加请求头(在原来的基础上添加)
addHeaders(Map<String, List<String>> params)//添加多个请求头
basicAuthentication(String username, String password)//提供与请求一起发送的基本身份验证凭据
缓存&超时&header回调
noCache() //取消此请求的缓存
setTimeout(int timeoutMilliseconds)//设置请求超时(毫秒)超时将抛出CancellationException
onHeaders(HeadersCallback callback)//收到请求头时,调用给指定回调(用来解析请求头)
group(Object groupKey)//可以给请求设置组,同一组的请求 groupKey必须相同(因为在取消请求的方法中可以取消一组请求)
请求参数
setBodyParameter(String name, String value)//设置请求参数(默认是POST,以下都是)
setBodyParameters(Map<String, List<String>> params)//设置多个请求参数
addQuery(String name, String value)//添加请求参数
addQueries(Map<String, List<String>> params)//添加多个请求参数
setJsonObjectBody(JsonObject jsonObject)//使用 JsonObj 作为参数去请求
setJsonPojoBody(T object)//使用 Json封装的对象 作为参数
setJsonArrayBody(JsonArray jsonArray)//使用 JsonArray 作为参数
setStringBody(String string)//使用 String 作为参数
setDocumentBody(Document document)//使用 Xml文档 作为参数
setFileBody(File file)//使用 File文件 作为参数
setByteArrayBody(byte[] bytes)//使用 Byte数组 作为参数
setStreamBody(InputStream inputStream)//使用 input输入流 作为参数
返回类型
asJsonArray(Charset charset)//以 JsonArray 类型返回数据(Charset:指定解码的编码)
asJsonObject(Charset charset)//以 JsonObject类型返回数据
asString() //以 String 类型返回数据
asInputStream()//以 stream流的方式返回数据(会将整个数据加载到内存,不建议用于大的请求返回)
asDocument() //以 XML文档 类型返回数据
asByteArray() //以 byte [] arr 类型返回数据
write(T outputStream)//将返回数据直接写入输出流中
write(File file)//讲返回数据直接写入文件中
图片相关
withBitmap() //请求返回一张图片
placeholder(Drawable drawable)//加载请求时,占位图片
placeholder(int resourceId)//同上
error(Drawable drawable)//请求失败时,占位图片
animateIn(Animation in)//文件或URL请求成功时,显示图片的一个动画(默认是淡入)
animateIn(int animationResource)//同上
animateLoad(Animation load)//图片加载时的动画
animateLoad(int animationResource)//同上
fadeIn(boolean fadeIn)//是否使用默认的淡入动画
animateGif(AnimateGifMode mode)//给GIF设置动画类型:AnimateGifMode.NO_ANIMATE/ANIMATE/ANIMATE_ONCE;(无动画,有重复,有执行1次)
deepZoom() //完全保真的方式加载,只有图像的部分被解码
intoImageView(ImageView imageView)//直接将返回图片显示在ImageView上
下载或请求的进度 和 回调
progressBar(ProgressBar progressBar)//在请求期间指定要更新的ProgressBar
progressDialog(ProgressDialog progressDialog)//在请求期间指定要更新的ProgressDialog
progress(ProgressCallback callback)//指定在下载进度时调用的回调。 (注意回调不在 主线程UI线程)
progressHandler(ProgressCallback callback)//同上(但是这个回调是在主线程的UI线程)
上传的进度 和 回调
setMultipartParameter(String name, String value)//指定请求的 multipart/form-data参数。(还没搞懂,但是不影响上传文件)
setMultipartParameters(Map<String, List<String>> params)//同上 只是可以指定一组 多个
setMultipartFile(String name, File file)//设置上传的文件(name:是指key,并不一定是文件名,file是要上传的文件)
setMultipartFile(String name, String contentType, File file)//同上(参数2:文件的MIME类型)
uploadProgress(ProgressCallback callback)//设置上传时进度回调(获取上传的进度)
uploadProgressHandler(ProgressCallback callback)//同上(这个回调是在UI线程中调用)
uploadProgressBar(ProgressBar progressBar)//可以直接将progressBar进行设置,同步上传进度
uploadProgressDialog(ProgressDialog progressDialog)//可以直接将progressBar进行设置,同步上传进度
设置请求回调
setCallback(Callback)//设置回调 回调的数据类型 基于asXXX
几种数据的简单获取方式:
Future<String> string = Ion.with(context).load("http://example.com/string.txt").asString();
Future<JsonObject> json = Ion.with(context).load("http://example.com/json.json").asJsonObject();
Future<File> file = Ion.with(context).load("http://example.com/file.zip").write(new File("/sdcard/file.zip"));
Future<Bitmap> bitmap = Ion.with(context).load("http://example.com/image.png").intoImageView(imageView);
JsonObject json = Ion.with(context).load("http://example.com/thing.json").asJsonObject().get();
5.取消请求
Ion.getDefault(activity).cancelAll(activity);Ion.getDefault(activity).cancelAll();Ion.getDefault(activity).cancelAll(group);
6.Utils封装
* 创建时间: 2017/3/27 22:03
* 描述:
*/
public class IonUtils {
public static final String GET = "GET";
public static final String POST = "POST";
private static final int timeOut = 10000;
private static final boolean isCache = true;
/**
* 上传文件(可以根据需求修改参数,如果上传多个文件,setMultipartFile的参1不变,继续添加文件即可)
*
* @param context 上下文对象
* @param url 请求的url
* @param file 上传的文件
* @param contentType 文件的类型 例如:application/zip
* @param progressBar 上传进度显示的progerssBar
* @param progressCallback 上传进度的回调
* @param callback 上传结果的回调
*/
public static void uploadFile(Context context, String url, File file, String contentType, ProgressBar progressBar, ProgressCallback progressCallback,FutureCallback<String> callback) {
if(!file.exists() || file == null){
throw new RuntimeException("file is not exists, or is null!");
}
Ion.with(context)
.load(url)
.uploadProgressBar(progressBar)
.uploadProgressHandler(progressCallback)
.setMultipartFile("archive", contentType, file)
.asString()
.setCallback(callback);
}
/**
* 下载文件 并 写入到指定的文件中
* @param context 上下文
* @param url 请求下载文件的url
* @param progressBar 下载进度现实的progressBar
* @param progressDialog 同上
* @param progressCallback 下载进度的回调
* @param targetFile 写入的目标文件
* @param callback 下载请求的回调(包含了要下载的文件)
*/
public static void downloadFile(Context context, String url, ProgressBar progressBar, ProgressDialog progressDialog,
ProgressCallback progressCallback,File targetFile,FutureCallback<File> callback
){
if(!targetFile.exists() || targetFile == null){
throw new RuntimeException("file is not exists, or is null!");
}
Ion.with(context)
.load(url)
.progressBar(progressBar)
.progressDialog(progressDialog)
.progress(progressCallback)
.write(targetFile)
.setCallback(callback);
}
/**
* 1:请求的封装(可以更改其返回数据类型,可以asJsonArray,asJsonObject,asInputStream,asDocument,asByteArray)回调的 泛型 是根据asXXX来指定的
* 2:也可以直接write将返回的数据直接写入文件中
* 3:回调的参数中有个Exception 如果不为null就代表 请求失败
* 4:请求的参数也可以修改,将setBodyParameters可改为setJsonObjectBody,setJsonPojoBody,setJsonArrayBody,setDocumentBody,setStreamBody等等
* 5:注意:header 和 请求参数 不可以为null 如果不需要的话 可以去掉参数,但不可以传入null 会报错。
*
* @param context 上下文
* @param method 请求的method
* @param url 请求的url
* @param headerParams 请求头
* @param bodyParams 请求参数
* @param callback 回调
*/
public static void requestAsString(Context context, String method, String url, Map<String, List<String>> headerParams, Map<String, List<String>> bodyParams, FutureCallback<String> callback) {
Ion.with(context)
.load(method, url)
.setTimeout(timeOut)
.addHeaders(headerParams)
.setBodyParameters(bodyParams)
.asString()
.setCallback(callback);
}
/**
* 请求图片并显示在指定的ImageView上(如果要加载的是GIF 其他的都不变 只需要设置gif的显示方式即可)
* animateGif(AnimateGifMode mode) AnimateGifMode.NO_ANIMATE/ANIMATE/ANIMATE_ONCE;(无动画,有重复,有执行1次)
* @param context
* @param url
* @param placeId 加载时显示的图片
* @param errorId 请求失败时显示的图片
* @param animationIn 请求成功时的动画(默认是 淡入),如果想取消调用 fadeIn(false);即可
* @param animationLoad 加载时的动画
* @param imageView 最终显示图片的ImageView
*/
public static void requestDrawable(Context context,String url,int placeId,int errorId,
Animation animationIn,Animation animationLoad,ImageView imageView
){
Ion.with(context)
.load(url)
.withBitmap()
.placeholder(placeId)
.error(errorId)
.animateLoad(animationLoad)
.animateIn(animationIn)
.intoImageView(imageView);
}
/**
* 从assets 文件中获取图片
* @param context
* @param fileName 图片名称
* @return
* @throws Exception
*/
public static Bitmap getBitmapForAssets(Context context,String fileName)throws Exception{
Bitmap bitmap = Ion.with(context)
.load("file:///android_asset/"+fileName)
.asBitmap()
.get();
assertNotNull(bitmap);
return bitmap;
}
/**
* 请求一个 按指定的 宽高裁剪后的图片
* @param context
* @param url
* @param cutWidth 裁剪的宽度
* @param cutHeight 裁剪的高度
* @return
* @throws Exception
*/
public static Bitmap requestCroppBitmap(Context context,String url,int cutWidth,int cutHeight) throws Exception{
Bitmap bitmap = Ion.with(context)
.load(url)
.withBitmap()
.resize(cutWidth, cutHeight)
.centerCrop()
.asBitmap()
.get();
assertEquals(bitmap.getWidth(), cutWidth);
assertEquals(bitmap.getHeight(), cutHeight);
// 像素不应该清晰
int pixel = bitmap.getPixel(cutWidth-1, cutHeight-1);
System.out.println(String.format("%x", pixel));
assertFalse(0 == pixel);
return bitmap;
}
/**
* 获取gif 图片
* @param context
* @param url
* @return
* @throws Exception
*/
public static GifFrame requestGif(Context context,String url)throws Exception{
byte[] bytes = Ion.with(context)
.load(url)
.asByteArray() //将gif数据返回成 字节数据
.get(); //封装成字节数组
GifDecoder decoder = new GifDecoder(bytes);
//两种方式封装获取 gif
//GifFrame frame = decoder.nextFrame();
GifFrame frame = decoder.nextFrame();
return frame;
}
/**
* 取消指定Activity的请求
* @param activity 要取消请求的Activity
*/
public static void cancelRequest(Activity activity){
Ion.getDefault(activity).cancelAll(activity);
}
/**
* 取消所有的Ion请求
* @param context
*/
public static void cancelAllRequest(Context context){
Ion.getDefault(context).cancelAll();
}
}