經(jīng)常需要下載網(wǎng)絡(luò)上的圖片到本地闯参,比如用戶頭像之類的哑蔫,這里采用rxjava+retrofit的形式去實(shí)現(xiàn)這個(gè)功能
HttpManager 類:就是一個(gè)通過單例模式實(shí)現(xiàn)的類后德,獲取retrofit的一個(gè)實(shí)例來調(diào)用NetApi接口內(nèi)聲明的方法友扰,此處只寫關(guān)鍵的一部分,別的相信你們都會(huì)
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后面不加任何東西格了,平時(shí)的都是@GET("api/getuserinfo")
之類的和上面的那個(gè)BASE_URl拼接起來生成url:
http://www.xxxx.com:8080/api/getuserinfo?請(qǐng)求條件=xx
然后去請(qǐng)求,這里采用@Url注解的方式就不用那么麻煩了
@Url 此處是動(dòng)態(tài)url即網(wǎng)絡(luò)圖片的url徽鼎,需要從外部傳入盛末,如度娘圖標(biāo)url:
https://www.baidu.com/img/superlogo_c4d7df0a003d3db9b65e9ef0fe6da1ec.png
用字符串的形式傳入即可
Presenter類 :發(fā)起網(wǎng)絡(luò)請(qǐng)求把得到的圖片二進(jìn)制流轉(zhuǎn)化為bitmap對(duì)象,再通過bitmap對(duì)象保存到本地指定目錄下
/**
* 指定線程下載文件(異步)否淤,非阻塞式下載
*
* @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內(nèi)的方法悄但,把二進(jìn)制流轉(zhuǎn)化為bitmap,需要導(dǎo)入系統(tǒng)包:
import android.graphics.BitmapFactory;
FileUtils類:IO操作石抡,把圖片保存到本地:
/**
* 保存圖片到SD卡
*
* @param bm 圖片bitmap對(duì)象
* @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中調(diào)用:
mPresenter.downloadFile("https://www.baidu.com/img/superlogo_c4d7df0a003d3db9b65e9ef0fe6da1ec.png", Environment.getExternalStorageDirectory() + File.separator + "test", "baidu")
執(zhí)行結(jié)果:
后記:如果你是mvp的架構(gòu)在onNext檐嚣,onError或者onComplete中回調(diào)你view中的方法時(shí),請(qǐng)注意要切到主線程中處理
observeOn(AndroidSchedulers.mainThread())
,不然可能會(huì)報(bào)出異常汁雷,還有就是記得獲取讀寫sd卡的權(quán)限