編輯:關於Android編程
學習RxJava有一段時間了,一直在考慮怎麼使用,如何在項目中合理運用它。在android很多項目中,都會存在圖片上傳,下面我介紹如何用Rxjava異步上傳多張圖片。
一,用到的框架
compile 'top.zibin:Luban:1.0.9'//圖片壓縮 compile 'org.xutils:xutils:3.3.34'//網絡請求 compile 'io.reactivex:rxandroid:1.1.0'//rxandroid compile 'io.reactivex:rxjava:1.1.0'//rxjava
另外Rxjava與Lambda表達式非常契合,便引入了Lambda的配置,在gradle中需要支持java8的特性:
jackOptions { enabled true } compileOptions { targetCompatibility JavaVersion.VERSION_1_8 sourceCompatibility JavaVersion.VERSION_1_8 }
初始化配置,在自己的Application的onCreate中需要初始化網絡請求框架,否定會無法進行網絡請求。
public class APP extends Application { private static APP instance; public static synchronized APP getInstance() { return instance; } @Override public void onCreate() { super.onCreate(); x.Ext.init(this); x.Ext.setDebug(org.xutils.BuildConfig.DEBUG); instance = this; } }
二,圖片壓縮與上傳
這裡為了演示用法與圖片上傳只是模擬請求所以手動創建了三個數組用來緩存圖片選擇後和處理後的url。
private List<String> mImageList; private List<String> mReduceImageList; private List<String> mImageUrl; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mImageUrl = new ArrayList<>(); mImageList = new ArrayList<>(); mReduceImageList = new ArrayList<>(); mImageList.add("content://media/external/images/media/573778"); mImageList.add("content://media/external/images/media/573778"); mImageList.add("content://media/external/images/media/573778"); Button button = (Button) findViewById(R.id.button1); button.setOnClickListener(v -> setImage()); }
圖片上傳大部分是根據拍照或者圖庫選擇的多張Uri地址,如果不進行壓縮,圖片都是很大的,一般拍照的圖片都有幾百KB或者幾M,所以為了節省流量與服務器的承載負擔,需要進行壓縮。壓縮後的圖片大小僅在幾十KB左右。
/** * 根據uri查詢位置圖片 * * @param selectedImage */ private void sendPicByUri(Uri selectedImage) { Cursor cursor = getContentResolver().query(selectedImage, null, null, null, null); String st8 = "沒有找到圖片"; if (cursor != null) { cursor.moveToFirst(); int columnIndex = cursor.getColumnIndex("_data"); String picturePath = cursor.getString(columnIndex); cursor.close(); if (picturePath == null || picturePath.equals("null")) { Toast toast = Toast.makeText(this, st8, Toast.LENGTH_SHORT); toast.setGravity(Gravity.CENTER, 0, 0); toast.show(); return; } sendPicture(picturePath); } else { File file = new File(selectedImage.getPath()); if (!file.exists()) { Toast toast = Toast.makeText(this, st8, Toast.LENGTH_SHORT); toast.setGravity(Gravity.CENTER, 0, 0); toast.show(); return; } sendPicture(file.getAbsolutePath()); } } /** * 壓縮圖片 * * @param filePath */ private void sendPicture(final String filePath) { Log.i(tag, "壓縮圖片"); Luban .get(this) .load(new File(filePath)) .putGear(Luban.THIRD_GEAR) .setCompressListener(new OnCompressListener() { @Override public void onStart() { } @Override public void onSuccess(File file) { Log.i(tag, "壓縮後的圖片==》"); uploadImg(file); } @Override public void onError(Throwable e) { } }) .launch(); setResult(RESULT_OK); }
為了優化代碼和這些耗時操作用到的RxJava,進行異步處理,我們需要創建RxJava的寫法:
/** * 分發url 接收者 */ private Func1<List<String>, Observable<String>> mOneLetterFunc = Observable::from; private Action1<String> mImageUrlAction = s -> uploadImg(new File(s)); private Action1<String> mAddContent = s -> sendPicByUri(Uri.parse(s)); /** * 分發壓縮圖片 */ private void setImage() { Log.i(tag, "開始分發獲取的url"); Observable.just(mImageList) .subscribeOn(Schedulers.io()) // 指定 subscribe() 發生在 IO 線程 .observeOn(AndroidSchedulers.mainThread()) .flatMap(mOneLetterFunc) .subscribe(mAddContent); }
分發的同事會進行異步網絡請求,進行上傳圖片至服務器,並返回服務器所存儲的url圖片地址:
/** * 圖片上傳服務器 * * @param file 文件 */ public void uploadImg(File file) { Log.i(tag, "網絡請求上傳圖片"); RequestParams params = new RequestParams("這裡是上傳到服務器的Http地址"); params.addBodyParameter("imgContent", file); params.setMultipart(true); x.http().post(params, new Callback.ProgressCallback<String>() { @Override public void onWaiting() { } @Override public void onStarted() { } @Override public void onLoading(long total, long current, boolean isDownloading) { } @Override public void onSuccess(String result) { try { JSONObject jsonObject = new JSONObject(result); JSONObject data = jsonObject.getJSONObject("data"); mImageUrl.add(data.getString("src")); if (mImageList.size() == mImageUrl.size()) { Log.i("上傳完成==", mImageUrl.toString()); } } catch (JSONException e) { e.printStackTrace(); } } @Override public void onError(Throwable ex, boolean isOnCallback) { Log.i("上傳出錯==", ex.getMessage()); } @Override public void onCancelled(CancelledException cex) { } @Override public void onFinished() { } }); }
為了節約時間,也可以在添加圖片時就進行壓縮圖片等操作。上傳時,只進行上傳的網絡操作
/** * 直接上傳所選圖片圖片 */ private void uploadingImage() { Log.i(tag, "開始上傳圖片"); if (mReduceImageList.size() > 0) { Observable.just(mReduceImageList) .subscribeOn(Schedulers.io()) // 指定 subscribe() 發生在 IO 線程 .observeOn(AndroidSchedulers.mainThread()) .flatMap(mOneLetterFunc) .subscribe(mImageUrlAction); } }
三,小結
這裡只是簡單的演示Rxjava的基本用法,其強大毋庸置疑,但要運用好,還需要深入去學習它。它也讓我們的代碼更簡潔。學習永無止境,感謝大佬們給我們提供的那麼多好用的框架。
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持本站。
Android 開機自啟動示例程序。使用廣播方式接受,采用Android自帶存儲SharedPreferences存儲開機自啟動的設置。本文源碼:點擊1、先加上權限&nb
我們經常遇到一個需求,就是給別人使用我們工程的時候,為了能夠屏蔽代碼,把代碼封裝成jar包提供給第三方使用,但是這樣我們的資源文件怎麼給對方用呢? 網上有很多方法,有用C
Android下拉刷新庫,利用viewdraghelper實現。集成了下拉刷新,底部加載更多,以及剛進入加載數據的loadview。包括了listview與g
本文詳細分析了Android中Service服務。分享給大家供大家參考,具體如下:一、Service簡介Service是Android中實現程序後台運行的解決方案,適用於