rxjava 2.x+retrofit 通过动态url保存网络图
2019-02-18 本文已影响5人
青衿尘
封面.jpg
经常需要下载网络上的图片到本地,比如用户头像之类的,这里采用rxjava+retrofit的形式去实现这个功能
HttpManager 类:就是一个通过单例模式实现的类,获取retrofit的一个实例来调用NetApi接口内声明的方法,此处只写关键的一部分,别的相信你们都会
public <T> T getHttpApi(Class<T> service) {
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(BASE_URl)
.client(getClient())
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.build();
return retrofit.create(service);
}
BASE_URl 是你定义的域名比如:http://www.xxxx.com:8080之类的
NetApi接口:
@GET
@Streaming
Observable<ResponseBody> downLoadImg(@Url String imgUrl);
注意注解:
@GET后面不加任何东西,平时的都是@GET("api/getuserinfo")
之类的和上面的那个BASE_URl拼接起来生成url:
http://www.xxxx.com:8080/api/getuserinfo?请求条件=xx
然后去请求,这里采用@Url注解的方式就不用那么麻烦了
@Url 此处是动态url即网络图片的url,需要从外部传入,如度娘图标url:
https://www.baidu.com/img/superlogo_c4d7df0a003d3db9b65e9ef0fe6da1ec.png
用字符串的形式传入即可
Presenter类 :发起网络请求把得到的图片二进制流转化为bitmap对象,再通过bitmap对象保存到本地指定目录下
/**
* 指定线程下载文件(异步),非阻塞式下载
*
* @param url 图片url
* @param savePatch 下载文件保存目录
* @param fileName 文件名称(不带后缀)
*
*/
public void downloadFile(String url, final String savePatch, final String fileName) {
HttpManager.getInstance().getHttpApi(NetApi.class)
.downLoadImg(url)
.subscribeOn(Schedulers.io())
.observeOn(Schedulers.newThread())
.subscribe(new DisposableObserver<ResponseBody>() {
@Override
public void onNext(ResponseBody responseBody) {
Bitmap bitmap = null;
byte[] bys;
try {
bys = responseBody.bytes();
bitmap = BitmapFactory.decodeByteArray(bys, 0, bys.length);
try {
FileUtils.saveImg(bitmap, savePatch, fileName);
String savePath = savePatch + File.separator + fileName + ".jpg";
} catch (IOException e) {
e.printStackTrace();
}
} catch (IOException e) {
e.printStackTrace();
}
if (bitmap != null) {
bitmap.recycle();
}
}
@Override
public void onError(Throwable e) {
//你的处理
}
@Override
public void onComplete() {
//你的处理
}
});
}
decodeByteArray是BitmapFactory内的方法,把二进制流转化为bitmap,需要导入系统包:
import android.graphics.BitmapFactory;
FileUtils类:IO操作,把图片保存到本地:
/**
* 保存图片到SD卡
*
* @param bm 图片bitmap对象
* @param floderPath 下载文件保存目录
* @param fileName 文件名称(不带后缀)
*/
public static void saveImg(Bitmap bm, String floderPath, String fileName) throws IOException {
//如果不保存在sd下面下面这几行可以不加
if (!Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
Log.e("SD卡异常");
return;
}
File folder = new File(floderPath);
if (!folder.exists()) {
folder.mkdirs();
}
String savePath = folder.getPath() + File.separator + fileName + ".jpg";
File file = new File(savePath);
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(file));
bm.compress(Bitmap.CompressFormat.JPEG, 80, bos);
Log.d(savePath + " 保存成功");
bos.flush();
bos.close();
}
在你的service或者activity中调用:
mPresenter.downloadFile("https://www.baidu.com/img/superlogo_c4d7df0a003d3db9b65e9ef0fe6da1ec.png", Environment.getExternalStorageDirectory() + File.separator + "test", "baidu")
执行结果:
result.png后记:如果你是mvp的架构在onNext,onError或者onComplete中回调你view中的方法时,请注意要切到主线程中处理
observeOn(AndroidSchedulers.mainThread())
,不然可能会报出异常