rxjava 2.x+retrofit 通過動態url儲存網路圖片到本地

封面.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 StringimgUrl);
注意註解:
@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())
,不然可能會報出異常