rxjava上傳文件
Ⅰ 在android中怎樣用rxjava傳遞數據在不同界面
一個是繼承,一個是實現介面,繼承這個可以理解為繼承父類的方法,父類中的方法可以在子類中用到,super(),實現介面就是在介面中定義了方法,這個方法要你自己去實現,介面可以看作一個標准,比如定義了一個動物的介面,它裡面有吃(eat())這個方法,你就可以實現這個方法implements,這個方法是自己寫,可以是吃蘋果,吃梨子,香蕉,或者其他的。IMPLEMENTS就是具體實現這個介面。
Ⅱ 重識OkHttp——更深入了解如何使用
OkHttp作為square公司出品的一個網路請求框架,應該算是目前Android端最火爆的網路框架了。我公司目前的項目中採用的都是Rxjava結合Retrofit進行網路請求的處理,對於底層真正實現網路請求的OkHttp關注的不是很多。最近探究了一下OkHttp的源碼,對OkHttp的使用有了一些新的認識,在此做一下總結。
OkHttp作為當前Android端最火熱的網路請求框架,必然有很多的優點。
對於客戶端來講,我們關注的就是把正確的請求發送到服務端並拿到結果來進行處理。在OkHttp中,我認為可以分為3個部分:
OkHttp中通過建造者模式來構建OkHttpClient、Request和Response。對於客戶端來講,我們不需要過多關注Response是如何構建的,因為這個是OkHttp對響應結果進行了封裝處理。我們只關注請求Request和客戶端OkHttpClient如何構建即可。
Request採用建造者模式來配置url,請求方法method、header、tag和cacheControl。
OkHttp採用POST方法向伺服器發送一個請求體,在OkHttp中這個請求體是RequestBody。這個請求體可以是:
RequestBody有幾個靜態方法用於創建不同類型的請求體:
最終都是相當於重寫了RequestBody的兩個抽象方法來寫入流,如果傳遞流類型的參數,只要重寫這兩個抽象方法即可。
例如,我們提交一個String:
提交File:
提交流:
對於提交表單和分塊請求,OkHttp提供了兩個RequestBody的子類, FormBody 和 MultipartBody
FormBody也是採用建造者模式, 這個很簡單,添加key-value形式的鍵值對即可。
添加鍵值對有兩個方法:
例如:
MultipartBody也是採用建造者模式,MultipartBody.Builder可以構建兼容Html文件上傳表單的復雜請求體。每一部分的多塊請求體都是它自身的請求體,並且可以定義它自己的請求頭。如果存在的話,這些請求頭用來描述這部分的請求體。例如Content-Disposition、Content-Length 和 Content-Type如果可用就會被自動添加到頭。
MIME類型有:
有幾個主要的方法:
例如提交一個圖片文件:
OkHttpClient採用建造者模式,通過Builder可以配置連接超時時間、讀寫時間,是否緩存、是否重連,還可以設置各種攔截器interceptor等。
建議在一個App中,OkHttpClient保持一個實例。一個OkHttpClient支持一定數量的並發,請求同一個主機最大並發是5,所有的並發最大是64。這個與OkHttp中的調度器Dispatcher有關,可以設置並發數。本文不對Dispatcher進行討論。
一個例子:
OkHttpClient支持單獨配置,例如原來設置不同的請求時間,可以通過OkHttpClient的newBuilder()方法來重新構造一個OkHttpClient。例如:
上面已經講了如何創建Request和OkHttpClient,剩下的就是發送請求並得到伺服器的響應了。OkHttp發送請求可分為同步和非同步。OkHttpClient首先通過Request構建一個Call,通過這個Call去執行同步或者非同步請求。
同步方式,調用Call的execute()方法,返回Response,會阻塞當前線程:
非同步方式,調用Call的enqueue(CallBack callBack)方法,會在另一個線程中返回結果。
為了緩存響應,需要一個可讀寫並且設置大小Size的緩存目錄。緩存目錄需要私有,其它不信任的應用不能訪問這個文件。
如果同時有多個緩存訪問同一個緩存目錄會報錯。所以最好只在App中初始化一次OkHttpClient,給這個實例配置緩存,在整個App生命周期內都用這一個緩存。否則幾個緩存會相互影響,導致緩存出錯,引起程序崩潰。
響應緩存採用Http頭來配置,你可以添加這樣的請求頭 Cache-Control: max-stale=3600 。 max-age 指的是客戶端可以接收生存期不大於指定時間(以 秒 為單位)的響應。
為了防止響應使用緩存,可以用 CacheControl.FORCE_NETWORK 。為了防止使用網路,採用 CacheControl.FORCE_CACHE 。
調用Call.cancel()方法可以立即取消一個網路請求。如果當前線程正在寫request或者讀response會報IO異常。如果不再需要網路請求,採用這種方法是比較方便的。例如在App中返回了上一頁。無論是同步還是非同步的請求都可以被取消。
可以通過Response的code來判斷請求是否成功,如果伺服器返回的有數據,可以通過Response的body得到一個ResponseBody讀取。
如果採用ResponseBody的string()方法會一次性把數據讀取到內存中,如果數據超過1MB可能會報內存溢出,所以對於超過1MB的數據,建議採用流的方式去讀取,如ResponseBody的byteStream()方法。
需要說明的是:
OkHttp中的很多類都用到了建造者模式,可以根據需要靈活配置。採用建造者模式的有:
如果單獨使用OkHttp進行網路請求,通常需要開發者自己再封裝一下,如果不想重復造輪子,Github上面的有一些優秀開源庫可以拿來使用(本文只列出star較多的幾個):
OkHttp官方Wiki文檔
Ⅲ Retrofit的淺析 —— 針對面試
1.近兩年Retrofit非常熱門,特別是結合Rxjava運用到項目中。Retrofit一個RESTful的Http網路請求框架的封裝,內部封裝了Okhttp網路請求框架,對網路請求做了大量優化。Retrofit其最大特點就是解耦,要解耦就需要大量的設計模式,內部使用了外觀模式、構建模式、觀察者模式、動態代理模式、策略模式、適配器模式和裝飾模式等等;
實際上分析Retrofit需要熟悉Okhttp才能深入分析Retrofit,Retrofit不止使用okhttp的內核,它還封裝了CallAdapter-請求適配器:可以實現多種請求響應形式:同步方式、非同步回調方式、RxJava方式;封裝了Converter-數據轉換器:可以自己定義responseBodyConverter和requestBodyConverter,實現加密功能和各種數據格式的解析;
retrofit 結合 okhttp 的原因就是retrofit使用了代理模式,默認代理走的就是okhttp,okhttp 負責網路請求, retrofit 負責對網路的處理,包括gson解析都是封裝在retrofit裡面的,如果哪天okttp不流行了是可以切換到別的網路框架的
Retrofit(改良)框架是Square公司出品的目前非常流行的網路框架,效率高,實現簡單,運用註解和動態代理設計模式,極大的簡化了網路請求的繁瑣步驟,非常適合處理REST ful(一種風格)網路請求.目前Retrofit版本是2(可以說是Square公司之前出品okhttp的升級版)
性能好,處理快,使用簡單.(速度比Volley更快)
使用REST API非常方便
支持NIO(新的IO API,可以替代標準的Java IO API)
Retrofit默認使用okhttp處理網路請求;
默認使用Gson解析
1.在項目的build.gradle中添加依賴後一個依賴比前一個多了個Gson解析的功能,看需求,二者依賴一個即可, 一 般依賴帶Gson解析的依賴
compile 'com.squareup.retrofit2:retrofit:2.0.0-beta4'
compile 'com.squareup.retrofit2:converter-gson:2.0.0-beta4'
<uses-permission android:name="android.permission.INTERNET" />
@GET GET網路請求方式
@POST POST網路請求方式
@Headers 頭信息參數
@Path 路徑參數.替換url地址中 "{" 和 "}"所包括的部分
@Query 查詢參數.將在url地址中追加類似"page = 1"的字元串,形成提交給伺服器端的請求參數
@QueryMap 查詢參數集合.在url地址中追加類似"type = text & count = 30 & page = 1 " 的字元串
@FormUrlEncoded 對表單域中填寫內存進行編碼處理,避免亂碼
@Field 指定from表單域中每個控制項的name及相應數值
@FieldMap 表單域集合
@Multipart Post提交分塊請求.如果上傳文件,必須指定Multipart
@Part Post提交分塊請求
@Body Post提交分塊請求
1.設置請求方式是註解的形式
2.介面拼接字元串更靈活
3.非同步響應回調方法在主線程
/**
* 作用:GET請求最簡單的寫法,無Path參數和Query參數
* article/list/latest?page=%d實際是Constant下的URL_LATEST地址
* @GET()里的東西是要拼接的網址,注意直接把page=1了
*/
@GET("article/list/latest?page=1")
Call<ResponseBody> getLatestJsonString();
/**
* 其中註解中的變數用{ 變數名自定義 } 在方法參數中
* 格式:@Path("上面定義的變數名") 類型 定義的變數名 作用:替換url地址中"{"和"}"所包括的部分
* 格式:@Query("參數名") 類型 定義的參數名 作用:會拼接在URL的最後部分,類似追加了"page = 1"的字元串,最後提交給伺服器
*/
@GET("article/list/{type}?")
Call<QiushiModel> getInfoList(@Path("type") String type, @Query("page") int page);
/**
* @QueryMap參數將在url地址中追加類似"type = text & count = 30 & page = 1 " 的字元串
*/
@GET("web/LoginServlet")
Call<ResponseBody> getRegInfo(@QueryMap Map<String, String> map);
/**
* 靜態的URL地址
*/
@GET("http://img.265g.com/userup/1201/201201071126534773.jpg")
Call<ResponseBody> getNetworkData();
/////////////////////////////////////////////////// Post ////////////////////////////////////////////////
/**
* 作用:post網路請求,向伺服器提交表單域數據
* @FormUrlEncoded:解決編碼亂碼問題,
*/
@FormUrlEncoded
@POST("web/LoginServlet")
Call<ResponseBody> postFormFields(@Field("username") String username,@Field("password") String password);
/**
* 作用:post網路請求,向伺服器提交表單域數據
* @FormUrlEncoded:解決編碼亂碼問題,
*/
@FormUrlEncoded
@POST("web/LoginServlet")
Call<ResponseBody> postFormFieldMap(@FieldMap Map<String , String> map);
/**
* 上傳單個文件,必須加上 @Multipart 註解
*/
@Multipart
@POST("web/UploadServlet")
Call<ResponseBody> postUploadFile(@Part("uploadfile\";filename=\"myuploadimg.png") RequestBody requestBody);
Retrofit2中Base Url與@Url不是簡單的組合,而是和<a href = "...">的處理方式一樣
提示:Base URL: 以"/"結尾 @Url:不要以"/"開頭
Ⅳ android開發框架有哪些
1、Rajawali
介紹:
安卓的OpenGL ES 2.0/3.0 引擎。可以用於製作普通應用或者動態壁紙,當然也可以用於製作游戲。
項目地址: https://github.com/Rajawali/Rajawali
2、RxAndroid
介紹:
RxAndroid是RxJava的一個針對Android平台的擴展。它包含了一些能夠簡化Android開發的工具。
項目地址: https://github.com/ReactiveX/RxAndroid
3、Paginize
介紹:
Paginize 是一個輕量級的UI框架,使用註解來注入布局和view,除了使用註解之外,該框架還有兩個特色:1.用Page的概念來取代Fragment,2.切換page時自帶ios風格的動畫效果。
項目地址: https://github.com/neevek/Paginize
4、otto
介紹:
Otto 是square公司出的一個事件庫(pub/sub模式),用來簡化應用程序組件之間的通訊。 Otto 修改自Google的Guava庫,專門為Android平台進行了優化。
項目地址: https://github.com/square/otto
5 、rebound
介紹:
rebound是facebook的開源動畫庫。可以認為這個動畫庫是獨立於android Framework之外的一種動畫實現。
項目地址: https://github.com/facebook/rebound
6、KJFrameForAndroid
介紹:
KJFrameForAndroid 又叫KJLibrary,是一個幫助快速開發的框架。使用KJFrameForAndroid,你可以只用一行代碼就完成http請求、網路圖片載入、資料庫數據保存或讀取。
項目地址: https://github.com/kymjs/KJFrameForAndroid
7、xUtils
介紹:
xUtils
包含了很多實用的android工具。 xUtils
支持大文件上傳,更全面的http請求協議支持(10種謂詞),擁有更加靈活的ORM,更多的事件註解支持且不受混淆影響... xUitls
最低兼容android 2.2 (api level 8)
項目地址: https://github.com/wyouflf/xUtils
目前xUtils主要有四大模塊:
DbUtils模塊:
android中的orm框架,一行代碼就可以進行增刪改查;
支持事務,默認關閉;
可通過註解自定義表名,列名,外鍵,唯一性約束,NOT NULL約束,CHECK約束等(需要混淆的時候請註解表名和列名);
支持綁定外鍵,保存實體時外鍵關聯實體自動保存或更新;
自動載入外鍵關聯實體,支持延時載入;
支持鏈式表達查詢,更直觀的查詢語義,參考下面的介紹或sample中的例子。
ViewUtils模塊:
android中的ioc框架,完全註解方式就可以進行UI,資源和事件綁定;
新的事件綁定方式,使用混淆工具混淆後仍可正常工作;
目前支持常用的20種事件綁定,參見ViewCommonEventListener類和包com.lidroid.xutils.view.annotation.event。
HttpUtils模塊:
支持同步,非同步方式的請求;
支持大文件上傳,上傳大文件不會oom;
支持GET,POST,PUT,MOVE,COPY,DELETE,HEAD,OPTIONS,TRACE,CONNECT請求;
下載支持301/302重定向,支持設置是否根據Content-Disposition重命名下載的文件;
返迴文本內容的請求(默認只啟用了GET請求)支持緩存,可設置默認過期時間和針對當前請求的過期時間。
BitmapUtils模塊:
載入bitmap的時候無需考慮bitmap載入過程中出現的oom和android容器快速滑動時候出現的圖片錯位等現象;
支持載入網路圖片和本地圖片;
內存管理使用lru演算法,更好的管理bitmap內存;
可配置線程載入線程數量,緩存大小,緩存路徑,載入顯示動畫等...
8、butterknife-view
注入工具
介紹:
為了減少頻繁的調用findViewById(R.id...),可以採用一些注入框架,可以簡化自己的代碼,讓你更專注於實際的功能開發,butterknife就是這樣的一個框架,他是jakewharton大神的作品,值得一試。
class ExampleActivity extends Activity {
@InjectView(R.id.title) TextView title;
@InjectView(R.id.subtitle) TextView subtitle;
@InjectView(R.id.footer) TextView footer;
@Override public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.simple_activity);
ButterKnife.inject(this);
// TODO Use "injected" views...
}
}
這是博客地址:
http://jakewharton.github.io/butterknife/
項目地址: https://github.com/JakeWharton/butterknife
9、cube-sdk
一淘推出的開發框架
介紹:
cube一個Android開發包, 可極大提高你的開發效率。主要提供了圖片載入以及網路請求方面的api功能。
項目地址: https://github.com/etao-open-source/cube-sdk
他們的網站:http://cube-sdk.liaohuqiu.net/cn/
10、ASimpleCache
一個簡單的緩存框架
介紹:
ASimpleCache
是一個為android制定的 輕量級的 開源緩存框架。輕量到只有一個java文件(由十幾個類精簡而來)。
它可以緩存什麼東西?普通的字元串、JsonObject、JsonArray、Bitmap、Drawable、序列化的java對象,和
byte數據。
項目地址: https://github.com/yangfuhai/ASimpleCache
11、androidannotations
介紹:
AndroidAnnotations是一個能夠讓你快速進行Android開發的開源框架,它能讓你專注於真正重要的地方。
使代碼更加精簡,使項目更加容易維護,它的目標就是「Fast Android Development.Easy maintainance」。
通過一段時間的使用發現,相比原生的Android開發,確實能夠讓你少些很多代碼
項目地址: https://github.com/excilys/androidannotations
12、Event Bus
解耦android模塊
介紹:
當一個Android應用功能越來越多的時候,保證應用的各個部分之間高效的通信將變得越來越困難。如何優雅地解決這個問題?這時候,就需要使用到EventBus。
EventBus是GreenRobot出品的Android系統的一個Event
Bus類庫,使用起來和之前我們所介紹的Square的Otto差不多,都是用來簡化應用組件之間的通信。
項目地址: https://github.com/greenrobot/EventBus
13、BeeFramework_Android
介紹:
BeeFramework
Android版主要為Android初級開發人員提供一個基於MVC開發模式的APP DEMO,並提供一套APP內調試工具,包括
查看網路數據請求歷史 Crash Log列表 真機WIFI環境下模擬2G\3G網路 查看APP性能(內存佔用,CPU佔用等)
項目地址: https://github.com/BeeFramework/BeeFramework_Android
14、afinal
介紹:
Afinal是一個android的ioc,orm框架,內置了四大模塊功能:FinalAcitivity,FinalBitmap,FinalDb,FinalHttp。通過finalActivity,我們可以通過註解的方式進行綁定ui和事件。通過finalBitmap,我們可以方便的載入bitmap圖片,而無需考慮oom等問題。通過finalDB模塊,我們一行代碼就可以對android的sqlite資料庫進行增刪改查。通過FinalHttp模塊,我們可以以ajax形式請求http數據。
Afinal裡面目前包含了四大組件:
FinalHttp:用於請求http數據,直接ajax方式請求,文件上傳, 斷點續傳下載文件等
FinalBitmap:用於顯示bitmap圖片,而無需考慮線程並發和oom等問題。
FinalActivity:完全可以通過註解方式綁定控制項和事件,無需編寫代碼。
FinalDb:android中sqlite的orm框架,一行代碼搞定增刪改查。
Afinal是一個android的ioc,orm框架,內置了四大模塊功能:FinalAcitivity,FinalBitmap,FinalDb,FinalHttp。通過finalActivity,我們可以通過註解的方式進行綁定ui和事件。通過finalBitmap,我們可以方便的載入bitmap圖片,而無需考慮oom等問題。通過finalDB模塊,我們一行代碼就可以對android的sqlite資料庫進行增刪改查。通過FinalHttp模塊,我們可以以ajax形式請求http數據。詳情請通過以下網址查看。
項目地址: https://github.com/yangfuhai/afinal
15、Volley
介紹:
在這之前,我們在程序中需要和網路通信的時候,大體使用的東西莫過於AsyncTaskLoader,HttpURLConnection,AsyncTask,HTTPClient(Apache)等,今年的Google
I/O 2013上,Volley發布了。Volley是Android平台上的網路通信庫,能使網路通信更快,更簡單,更健壯。
項目地址: https://github.com/mcxiaoke/android-volley
Ⅳ retrofit可以上傳大文件嗎
1.單張圖片的上傳
?
1
2
3
4
5
6
7
8
9
10
/**
* 上傳一張圖片
* @param description
* @param imgs
* @return
*/
@Multipart
@POST("/upload")
Call<String> uploadImage(@Part("fileName") String description,
@Part("file\"; filename=\"image.png\"")RequestBody imgs);
2.多張圖片的上傳
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
/**
* 上傳三張圖片
* @param description
* @param imgs
* @param imgs1
* @param imgs3
* @return
*/
@Multipart
@POST("/upload")
Call<String> uploadImage(@Part("fileName") String description,
@Part("file\"; filename=\"image.png\"")RequestBody imgs,
@Part("file\"; filename=\"image.png\"")RequestBody imgs1,
@Part("file\"; filename=\"image.png\"")RequestBody imgs3);
注意:目前是提供傳3張,要想多上傳目前我發現的方法就是想要多傳一張,就多增加一個參數
@Part("file\"; filename=\"image.png\"")RequestBody imgs,以此類推。
大家看到上面覺得寫法很漏,但是用於能力有限,只能想到這樣。用Java中的可變參數解決之後,就只能傳一張。不能多張。
?
1
2
3
4
@Multipart
@POST("/upload")
Call<String> uploadImage(@Part("fileName") String description,
@Part("file\"; filename=\"image.png\"")RequestBody ...imgs);
調用:
Call<String> call = apiManager.uploadImage( m[0],requestBody1,requestBody2,null);
這樣寫看上去很是高端,不幸的是只能傳一張
3.最後是實現胡過程
3.1創建FileUploadService介面
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
public interface FileUploadService {
/**
* 上傳一張圖片
* @param description
* @param imgs
* @return
*/
@Multipart
@POST("/upload")
Call<String> uploadImage(@Part("fileName") String description,
@Part("file\"; filename=\"image.png\"")RequestBody imgs);
/**
* 上傳三張圖片
* @param description
* @param imgs
* @param imgs1
* @param imgs3
* @return
*/
@Multipart
@POST("/upload")
Call<String> uploadImage(@Part("fileName") String description,
@Part("file\"; filename=\"image.png\"")RequestBody imgs,
@Part("file\"; filename=\"image.png\"")RequestBody imgs1,
@Part("file\"; filename=\"image.png\"")RequestBody imgs3);
}
3.2創建Retrofit對象
?
1
2
3
4
5
6
7
private static final Retrofit sRetrofit = new Retrofit .Builder()
.baseUrl(ENDPOINT)
.addConverterFactory(GsonConverterFactory.create())
// .addCallAdapterFactory(RxJavaCallAdapterFactory.create()) // 使用RxJava作為回調適配器
.build();
private static final FileUploadService apiManager = sRetrofit.create(FileUploadService.class);
3.3調用上傳的方法
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
public static void upload(String path){
String descriptionString = "hello, this is description speaking";
String[] m = new String[2];
m[0]= "share.png";
m[1]= "Screenshot_20160128-140709.png";
File[] ssssss= new File[2];
File file1 = new File("/storage/emulated/0/sc/share.png");
File file = new File("/storage/emulated/0/Pictures/ScreenShots/Screenshot_20160128-140709.png");
ssssss[0]=file;
ssssss[0]=file1;
RequestBody requestBody[] = new RequestBody[3];
RequestBody requestBody1 =
RequestBody.create(MediaType.parse("multipart/form-data"), file);
RequestBody requestBody2 =
RequestBody.create(MediaType.parse("multipart/form-data"), file1);
requestBody[0]=requestBody1;
requestBody[1]=requestBody2;
Call<String> call = apiManager.uploadImage( m[0],requestBody1,requestBody2,null);
call.enqueue(new Callback<String>() {
@Override
public void onResponse(Response<String> response, Retrofit retrofit) {
Log.v("Upload", response.message());
Log.v("Upload", "success");
}
@Override
public void onFailure(Throwable t) {
Log.e("Upload", t.toString());
}
});
}
4.伺服器段代碼:
伺服器用的是struts接收:
@Controller
public class GetToken extends ActionSupport {
/**
*
*/
private static final long serialVersionUID = 1L;
private File[] file;
private String[] fileName;
public File[] getFile() {
return file;
}
public void setFile(File[] file) {
this.file = file;
}
public String[] getFileName() {
return fileName;
}
public void setFileName(String[] fileName) {
this.fileName = fileName;
}
@Action("/upload")
public void login() {
System.out.println("------"+Arrays.toString(file));
System.out.println("------"+Arrays.toString(fileName));
}
}