標籤:

OkHttp在安卓中的使用?

之前一直用xutils,使用起來還算方便,但是好像官方不建議用了,所以就想換一套網路請求框架,看到大家對OkHttp十分看好,就去github上看了一番,發現非同步的callback還是在子線程里,不能像Xutils一樣方便的使用,因為對多線程不太熟悉,用Handler的post()每次都要new Runnable ,並不是太方便,不知道怎麼用比較好,想看看大家都是怎麼用的,希望各位大神給點兒意見。謝了


2015/11/16

-----------------------------------------------------------------------------------------------------------------

lsxiao/ZhihuDailyRRD · GitHub

2015/11/6 15:20

-----------------------------------------------------------------------------------------------------------------

忙得很,抽空規範了下注釋,小改了下布局,把5.0的視差嵌套滾動弄上去了,加上了日報的配圖。

2015/11/4 00:33

-----------------------------------------------------------------------------------------------------------------

一個RRD的例子基本上寫好了,只有兩個簡單的,查看當日新聞列表,和查看詳細新聞功能(沒有主題日報)。再改改就放GitHub

2015/11/4 00:33

-----------------------------------------------------------------------------------------------------------------

列表弄好了,顏色布局還要調一調。

2015/11/3 22:49

-----------------------------------------------------------------------------------------------------------------

調試了下Api,已經可以正常工作了,開始擼日報列表了。

2015/11/3 23:30

-----------------------------------------------------------------------------------------------------------------

想了想,就用RRD(Retrofit.RxJava.Dagger2)來寫個簡單的第三方知乎日報客戶端吧。

工程已經建好了,擼了點基類,每天下班了我會抽時間擼一下的。

2015/11/3 20:50

-----------------------------------------------------------------------------------------------------------------

評論有要完整例子的,這周我寫個簡單的例子放GitHub上面吧。

知乎上我就不寫了,編輯工具太難用了,不適合貼大量代碼。

2015/11/2 11:29

-----------------------------------------------------------------------------------------------------------------

感謝Max安珀的回復

OkHttp是Square開源Android版Http客戶端。除了OkHttp,Android自帶HttpURLConnection和HttpClient。

而Retrofit則在Http客戶端外繼續封裝了一層,讓你從伺服器獲取數據更加方便,所以說二者不矛盾。

Retrofit 2.0後默認使用的是OkHttp,2.0之前是可選的。

2015/10/31 21:14 更新由上而下,最新的編輯在最上面,所以你可能需要從下往上看了。

-----------------------------------------------------------------------------------------------------------------

前兩周左右,團隊開了新項目,而且我們團隊自己的框架正好迭代了新版本,集成了基於事件流的響應式編程框架RxJava。

所以我們Android組開了一個會,會上組長提出了這個項目要用RxJava配合Retrofit和Dagger2開發的要求。

真不巧,我所處的項目小組是第一個吃螃蟹的人(雖然Android組很大,但是項目組就只有4個人),而且我才入職三個月,第一次聽到Rx還是聽導師隨口說起的。

雖然我在讀大學的時候見過Dagger這幾個字母,但是我根本沒摸過它,我大學也就是用過ButterKnife的水平,更別說Dagger2了。

當時我就感覺很碉啊,簡直就是碉堡了,因為又有新的Android技術可以讓我折騰了,果然沒有來錯地方啊!

RxJava國內高質量的文章還是有的。

比如這一篇:

『匠心寫作』裡面的『給 Android 開發者的 RxJava 詳解』,是目前就職於Flipboard的『扔物線』寫的,通俗易懂。

但目前Dagger2在國內的中文資料還是很少,網上搜來搜去也就那幾篇,而且質量不高,感覺寫的人語文都學得不怎麼好。

所以我們組長親自動手,寫好了RxJava+Retrofit+Dagger2的配合使用文檔,並且弄好了項目的架構設計(簡直就是良心)。

當項目遇上了RxJava+Retrofit+Dagger2的巧妙結合,根本讓你欲罷不能,個中好處要用過才知道。

注【我不會講解Dagger2+RxJava+Retrofit它們分別的詳細使用方法,很占篇幅】

那麼我先舉個從伺服器獲取用戶數據的例子,看看如何用RxJava+Retrofit+Dagger2的方式來寫:

基本方式使用Retrofit和RxJava

//User Service
Service service = new ServiceImpl();

//創建Observable對象
Observable& observable= Observable.create(
new Observable.OnSubscribe&() {
@Override
public void call(Subscriber& subscriber) {
try {
User user =service.getUser("username","password")
subscriber.onNext(user);
subscriber.onCompleted();
} catch (Exception e) {
subscriber.onError(e);
}
}
});

//綁定訂閱者
observable.subscribeOn(Schedulers.io())//在IO線程進行網路請求,獲取數據
.observeOn(AndroidSchedulers.mainThread())//在UI線程操作數據
.subscribe(new Action1&() {
@Override
public void call(User user) {
//將userInfo數據顯示到UI上
}
});

上面的代碼在ServiceImpl類的getUser方法裡面使用了Retrofit獲取伺服器數據。

獲取數據是在RxAndroid提供的IO線程進行的,顯示數據是在UI線程進行的。

這就是基本的RxJava的用法了。

現在我們來看看上面的代碼有什麼缺點:

(1). service實例可以是單例模式,我們不需要在每處需要請求的地方都去重新實例化一個新的對象。

所以我們只需要實例化一次service對象,然後通過Dagger2把這個對象注入給一個全局變數(比如BaseActivity的成員變數)

這樣我們可以在任何地方獲取到它。

(2).還有創建Observable對象太麻煩了,其實Retrofit支持直接返回Observable類型的對象。

--------------------------------------------------------------------------------------------------------------

下面開始修改我們的代碼:

getService()//取得全局Service
.getUser("username","password")//調用返回Observable類型對象的方法
.subscribeOn(Schedulers.io())//在IO線程進行網路請求,獲取數據
.observeOn(AndroidSchedulers.mainThread())//在UI線程操作數據
.subscribe(new Action1&() {
@Override
public void call(User user) {
//將userInfo數據顯示到UI上
}
});

代碼是不是一下子減少了很多,之前的實例化Service和新建Observable的代碼都分散到了Dagger2的組件和模塊中,代碼的耦合度降低。

但是我們的Service可能不止一個啊,這個時候你可以繼續抽象一層DataLayer層出來。

通過一個DataLayer對象可以獲取所有的Service,這些Service都是單例的,且通過Dagger2注入。

我們可以在Application裡面初始化DataLayer對象,用單例模式,然後注入給BaseActivity,BaseFragment等等基類的成員變數。

這樣你在Fragment/Activity裡面直接調用

getDataLayer().getUserService().getUser().subscribeOn.....

有沒有覺得這種鏈式的調用方式很方便,很清晰,有一種碉堡的感覺?!

依賴關係圖:

2015/10/31 18:19

--------------------------------------------------------------------------------------------------------------

昨天很忙,沒時間講Rx+Retrofit+Dagger2怎麼配合開發的,今天先回家,吃了飯就開更。

2015/10/30

--------------------------------------------------------------------------------------------------------------

Retrofit支持返回Observale對象,這意味著我們可以使用RxAndroid(RxJava)來處理網路請求的問題。

在RxAndroid提供的IO線程裡面進行網路數據的請求,在主線程進行數據的顯示。

正好我們項目也是這麼做的,同時我們還使用了Dagger2來進行解耦操作。

今天有點忙,下午再來說說怎麼用Dagger2和Retrofit以及Rx很好的配合開發。


---------------------說好的更新分界線-----------------------

在Android應用開發中,我們不可避免的需要網路操作,尤其是在與伺服器頻繁的交互過程中,更是需要大量的重複編碼:HttpURLConnection,Thread, AsyncTask, Service等,十分複雜又容易出錯。在2013年Google I/O大會上推出了網路通信框架——Volley。它可以極大簡化HTTP通信,載入網路圖片的操作,並且在小數據量的頻繁網路交互中性能表現良好。不過,它不適合進行大文件的上傳下載。

基於上述原因,在最近的項目中我學習使用了Volley網路庫,然而Volley在使用中也存在一些問題:

比如,Volley自帶的JsonRequest只支持JSONObject,而如果想要使用Gson,還需要自己定製Request。

另外,默認情況下,Volley在Froyo使用Apache Http stack作為其傳輸層,而在Gingerbread及之後的版本上使用HttpURLConnection stack作為傳輸層。很自然我們想到,能不能將口碑十分好的OkHttp替換為Volley的傳輸層呢。

最後,很多時候我們需要一些小文件的上傳操作(如用戶頭像,批量上傳一些小圖片),能不能使用Volley完成這個任務呢。

所以,這裡描述一種結合使用Volley+OkHttp+Gson進行快速網路開發的方法,並給出一些網路介面封裝的例子。

-----------------下文代碼較多預警------------------

首先,要將OkHttp替換為Volley的傳輸層,需要實現一個OkHttpStack類,然後在實例化Volley的RequestQueue時將之替換即可:

RequestQueue mQueue = Volley.newRequestQueue(this, new OkHttpStack(new OkHttpClient()));

OkHttpStack類的實現網上有很多,個人使用的是來自GitHub的一個:OkHttpStack.java -- from GitHub

然後,我們需要實現使用Gson的Request類:

import com.android.volley.AuthFailureError;
import com.android.volley.NetworkResponse;
import com.android.volley.ParseError;
import com.android.volley.Request;
import com.android.volley.Response;
import com.android.volley.toolbox.HttpHeaderParser;
import com.google.gson.Gson;

import java.io.UnsupportedEncodingException;
import java.lang.reflect.Type;
import java.util.Map;

import me.zq.youjoin.utils.LogUtils;
import me.zq.youjoin.utils.StringUtils;

public class PostObjectRequest& extends Request& {

private ResponseListener listener;
private Gson gson;
private Type clazz;
private Map& params;

public PostObjectRequest(String url, Map& params, Type type,
ResponseListener listener){
super(Method.POST, url, listener);
this.listener = listener;
this.clazz = type;
this.params = params;
this.gson = new Gson();
}

@Override
protected Response& parseNetworkResponse(NetworkResponse response){
try{
T result;
String jsonString =
new String(response.data, HttpHeaderParser.parseCharset(response.headers));
LogUtils.d("hehe", jsonString);
result = gson.fromJson(StringUtils.FixJsonString(jsonString), clazz);
return Response.success(result,
HttpHeaderParser.parseCacheHeaders(response));
}catch (UnsupportedEncodingException e) {
return Response.error(new ParseError(e));
}
}

@Override
protected void deliverResponse(T response){
listener.onResponse(response);
}

@Override
protected Map& getParams() throws AuthFailureError{
return params;
}

}

最後,我們來實現圖片上傳部分。由於我們希望在上傳圖片的時候添加一些參數,例如用戶id等,導致這部分的實現比較複雜。雖然我們可以將這些信息存儲在圖片文件名中實現傳遞,但這總歸是取巧的辦法。比較正規一點的方法還是研究網頁表單提交時的Post請求的格式,然後自己構造一個合法的Post請求。我們可以使用Chorme的開發者工具來抓取Post請求,研究其格式,下圖為我抓取的一個帶圖片和參數的表單Post請求:

從圖中可以看出,我們只需要重寫getBody()方法,逐行仿照Post格式寫入我們自己的圖片和參數,就可實現參數+圖片的上傳。多張圖片的上傳原理相同。另外,圖片要注意在上傳之前進行壓縮處理。另外,為了方便伺服器解析多張圖片,將圖片參數設置為uploadedfile[index]格式。代碼如下:

import android.util.Log;

import com.android.volley.AuthFailureError;
import com.android.volley.DefaultRetryPolicy;
import com.android.volley.NetworkResponse;
import com.android.volley.ParseError;
import com.android.volley.Request;
import com.android.volley.Response;
import com.android.volley.toolbox.HttpHeaderParser;
import com.google.gson.Gson;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.Type;
import java.util.List;
import java.util.Map;

import me.zq.youjoin.model.ImageInfo;
import me.zq.youjoin.utils.StringUtils;

public class PostUploadRequest& extends Request& {

/**
* 正確數據的時候回掉用
*/
private ResponseListener mListener ;
/*請求 數據通過參數的形式傳入*/
private List& mListItem ;

private static final String BOUNDARY = "-----ZZQ----MZZ-----"; //數據分隔線
private static final String MULTIPART_FORM_DATA = "multipart/form-data";//使用表單數據方法提交
private static final String TAG = "hehe_upload_request";
private static final String PARAM = "uploadedfile";//圖片的參數,&為了上傳多張圖片,在下面的封裝中使用uploadedfile[index]格式作為圖片參數&

private Map& params;
private Gson gson;
private Type clazz;

public PostUploadRequest(String url, List& listItem,
Map& params,
Type type, ResponseListener listener) {
super(Method.POST, url, listener);
this.mListener = listener ;
this.params = params;
this.gson = new Gson();
this.clazz = type;
setShouldCache(false);
mListItem = listItem ;
//設置請求的響應事件,因為文件上傳需要較長的時間,所以在這裡加大了,設為5秒
setRetryPolicy(new DefaultRetryPolicy(5000,DefaultRetryPolicy.DEFAULT_MAX_RETRIES,DefaultRetryPolicy.DEFAULT_BACKOFF_MULT));
}

/**
* 這裡開始解析數據
* @param response Response from the network
* @return
*/
@Override
protected Response& parseNetworkResponse(NetworkResponse response) {
try {
String mString =
new String(response.data, HttpHeaderParser.parseCharset(response.headers));
Log.v(TAG, "mString = " + mString);
T result = gson.fromJson(StringUtils.FixJsonString(mString), clazz);
return Response.success(result,
HttpHeaderParser.parseCacheHeaders(response));
} catch (UnsupportedEncodingException e) {
return Response.error(new ParseError(e));
}
}

/**
* 回調正確的數據
* @param response The parsed response returned by
*/
@Override
protected void deliverResponse(T response) {

mListener.onResponse(response);
}
//重寫getBody()方法,封裝Post包
@Override
public byte[] getBody() throws AuthFailureError {
if (mListItem == null||mListItem.size() == 0){
return super.getBody() ;
}
ByteArrayOutputStream bos = new ByteArrayOutputStream() ;

if(!params.isEmpty()) {
StringBuilder sbParams = new StringBuilder();

for (Map.Entry& o : params.entrySet()) {
Map.Entry entry = (Map.Entry) o;

/*第一行*/
//`"--" + BOUNDARY + "
"`
sbParams.append("--" + BOUNDARY);
sbParams.append("
");
/*第二行*/
//Content-Disposition: form-data; name="參數的名稱"; + 參數 + "
"
sbParams.append("Content-Disposition: form-data;");
sbParams.append(" name="");
sbParams.append((String) entry.getKey());
sbParams.append(""");
sbParams.append("
");
sbParams.append("
");
sbParams.append((String) entry.getValue());
sbParams.append("
");
}
try {
bos.write(sbParams.toString().getBytes("utf-8"));
// bos.write("
".getBytes("utf-8"));
} catch (IOException e) {
e.printStackTrace();
}

}

int N = mListItem.size() ;
ImageInfo imageInfo ;
for (int i = 0; i &< N ;i++){ imageInfo = mListItem.get(i) ; StringBuilder sb= new StringBuilder() ; /*第一行*/ //`"--" + BOUNDARY + " "` sb.append("--"+BOUNDARY); sb.append(" ") ; /*第二行*/ //Content-Disposition: form-data; name="參數的名稱"; filename="上傳的文件名" + " " sb.append("Content-Disposition: form-data;"); sb.append(" name=""); sb.append(PARAM + "[" + Integer.toString(i) + "]"); //為了上傳多張圖片,使用uploadedfile[index]格式作為圖片參數 sb.append(""") ; sb.append("; filename="") ; sb.append(imageInfo.getFileName()) ; sb.append("""); sb.append(" ") ; /*第三行*/ //Content-Type: 文件的 mime 類型 + " " sb.append("Content-Type: "); sb.append(imageInfo.getMime()) ; sb.append(" ") ; /*第四行*/ //" " sb.append(" ") ; try { bos.write(sb.toString().getBytes("utf-8")); /*第五行*/ //文件的二進位數據 + " " bos.write(imageInfo.getValue()); bos.write(" ".getBytes("utf-8")); } catch (IOException e) { e.printStackTrace(); } } /*結尾行*/ //`"--" + BOUNDARY + "--" + " "` String endLine = "--" + BOUNDARY + "--" + " " ; try { bos.write(endLine.getBytes("utf-8")); } catch (IOException e) { e.printStackTrace(); } // Log.v(TAG,"imageInfo = "+bos.toString()) ; return bos.toByteArray(); } //Content-Type: multipart/form-data; boundary=----------8888888888888 @Override public String getBodyContentType() { return MULTIPART_FORM_DATA+"; boundary="+BOUNDARY; } // @Override //注意一旦重寫getBody()方法,則使用此方法添加參數無效。 // protected Map& getParams() throws AuthFailureError{
// return params;
// }
}

為了方便調用,封裝Response介面如下:

import com.android.volley.Response;

public interface ResponseListener& extends Response.ErrorListener,Response.Listener& {

}

至此,對Volley+OkHttp+Gson的封裝就完成了。在使用時,我們可以在自定義Application中初始化Queue,再封裝一個專門的NetworkManager類來提供所有的網路訪問操作,比如,在我最近的項目中是這樣用的:

/**
* 網路管理類,封裝網路操作介面
*/
public class NetworkManager {

/**
* 網路介面相關常量
*/
public static final String USER_USERNAME = "user_name";
public static final String USER_PASSWORD = "user_password";
public static final String USER_EMAIL = "user_email";
public static final String USER_ID = "user_id";
public static final String USER_WORK = "user_work";
public static final String USER_BIRTH = "user_birth";
public static final String USER_SIGN = "user_sign";
public static final String USER_LOCATION = "user_location";
public static final String USER_SEX = "user_sex";

public static final String TWEETS_CONTNET = "tweets_content";

public static final String FRIEND_ID = "friend_id";

public static final String SEND_USERID = "send_userid";
public static final String RECEIVE_USERID = "receive_userid";
public static final String MESSAGE_CONTENT = "message_content";

/**
* 伺服器介面URL
*/
public static final String BASE_API_URL = "http://192.168.0.103:8088/youjoin-server/controllers/";
public static final String API_SIGN_IN = BASE_API_URL + "signin.php";
public static final String API_SIGN_UP = BASE_API_URL + "signup.php";
public static final String API_UPDATE_USERINFO = BASE_API_URL + "update_userinfo.php";
public static final String API_SEND_TWEET = BASE_API_URL + "send_tweet.php";
public static final String API_REQUEST_USERINFO = BASE_API_URL + "request_userinfo.php";
public static final String API_ADD_FRIEND = BASE_API_URL + "add_friend.php";
public static final String API_SEND_MESSAGE = BASE_API_URL + "send_message.php";
public static final String API_RECEIVE_MESSAGE = BASE_API_URL + "receive_message.php";
public static final String API_COMMENT_TWEET = BASE_API_URL + "comment_tweet.php";
public static final String API_UPVOTE_TWEET = BASE_API_URL + "upvote_tweet.php";

private static RequestQueue mRequestQueue ;

/**
* 發送動態介面
* @param listener ResponseListener
*/
public static void postSendTweet(String content, List& images,
ResponseListener listener){
Map& params = new HashMap&<&>();
params.put(USER_ID, YouJoinApplication.getCurrUser().getId());
params.put(TWEETS_CONTNET, content);
Request request = new PostUploadRequest(API_SEND_TWEET, images, params,
new TypeToken&(){}.getType(), listener);
NetworkManager.getRequestQueue().add(request);
}

/**
* 發送私信介面
* @param receiveUserId 接收方用戶id
* @param content 私信內容
* @param listener ResponseListener
*/
public static void postSendMessage(String receiveUserId, String content,
ResponseListener listener){
Map& params = new HashMap&<&>();
params.put(SEND_USERID, YouJoinApplication.getCurrUser().getId());
params.put(RECEIVE_USERID, receiveUserId);
params.put(MESSAGE_CONTENT, content);
Request request = new PostObjectRequest(
API_SEND_MESSAGE,
params, new TypeToken&(){}.getType(),
listener);
NetworkManager.getRequestQueue().add(request);
}

/**
* 添加好友介面
* @param friendUserId 要添加的好友id
* @param listener ResponseListener
*/
public static void postAddFriend(String friendUserId,
ResponseListener listener){
Map& params = new HashMap&<&>();
params.put(USER_ID, YouJoinApplication.getCurrUser().getId());
params.put(FRIEND_ID, friendUserId);
Request request = new PostObjectRequest(
API_ADD_FRIEND,
params, new TypeToken&(){}.getType(),
listener);
NetworkManager.getRequestQueue().add(request);
}

/**
* 個人資料請求(下載)介面
* @param userId 要獲取的用戶id
* @param listener ResponseListener
*/
public static void postRequestUserInfo(String userId, ResponseListener listener){
Map& params = new HashMap&<&>();
params.put(USER_ID, userId);
Request request = new PostObjectRequest(
API_REQUEST_USERINFO,
params,new TypeToken&(){}.getType(),
listener);
NetworkManager.getRequestQueue().add(request);
}

/**
* 個人資料更新(上傳)介面
* @param userInfo 用戶實體類
* @param picPath 頭像的本地路徑
* @param listener ResponseListener
*/
public static void postUpdateUserInfo(UserInfo userInfo, String picPath, ResponseListener listener){
if(userInfo.getId() == null) return;

List& imageList = new ArrayList&<&>();
imageList.add(new ImageInfo(picPath));
Map& params = new HashMap&<&>();
params.put(USER_ID, userInfo.getId());
params.put(USER_WORK, userInfo.getWork());
params.put(USER_LOCATION, userInfo.getLocation());
params.put(USER_SEX, userInfo.getSex());
params.put(USER_BIRTH, userInfo.getBirth());
params.put(USER_SIGN, userInfo.getUsersign());
Request request = new PostUploadRequest(API_UPDATE_USERINFO, imageList, params,
new TypeToken&(){}.getType(), listener);
NetworkManager.getRequestQueue().add(request);
}

/**
* 登陸介面
* @param username 登錄用戶名
* @param password 登陸密碼
* @param listener ResponseListener
*/
public static void postSignIn(String username, String password,
ResponseListener listener){
Map& param = new HashMap&<&>();
param.put(USER_USERNAME, username);
param.put(USER_PASSWORD, Md5Utils.getMd5(password));
Request request = new PostObjectRequest(
API_SIGN_IN,
param,
new TypeToken&(){}.getType(),
listener);
NetworkManager.getRequestQueue().add(request);
}

/**
* 註冊介面
* @param username 註冊用戶名
* @param password 註冊密碼
* @param email 註冊郵箱
* @param listener ResponseListener
*/
public static void postSignUp(String username, String password, String email,
ResponseListener listener){
Map& param = new HashMap&<&>();
param.put(USER_USERNAME, username);
param.put(USER_PASSWORD, Md5Utils.getMd5(password));
param.put(USER_EMAIL, email);
Request request = new PostObjectRequest(
API_SIGN_UP,
param,
new TypeToken&(){}.getType(),
listener);
NetworkManager.getRequestQueue().add(request);
}

/**初始化Volley 使用OkHttpStack
* @param context 用作初始化Volley RequestQueue
*/
public static synchronized void initialize(Context context){
if (mRequestQueue == null){
synchronized (NetworkManager.class){
if (mRequestQueue == null){
mRequestQueue =
Volley.newRequestQueue(context, new OkHttpStack(new OkHttpClient()));
}
}
}
mRequestQueue.start();
}

/**獲取RequestQueue實例
* @return 返回RequestQueue實例
*/
public static RequestQueue getRequestQueue(){
if (mRequestQueue == null)
throw new RuntimeException("請先初始化mRequestQueue") ;
return mRequestQueue ;
}
}

import android.app.Application;
import android.content.Context;

import me.zq.youjoin.model.UserInfo;
import me.zq.youjoin.network.NetworkManager;

public class YouJoinApplication extends Application {
public static float sScale;
public static int sHeightPix;

private static Context context;

private static UserInfo currUser;

@Override
public void onCreate(){
super.onCreate();
context = getApplicationContext();
NetworkManager.initialize(context);

sScale = getResources().getDisplayMetrics().density;
sHeightPix = getResources().getDisplayMetrics().heightPixels;
}

public static Context getAppContext(){
return context;
}

public static UserInfo getCurrUser() {
return currUser;
}

public static void setCurrUser(UserInfo currUser) {
YouJoinApplication.currUser = currUser;
}
}

參考資料:

OkHttpStack.java -- from GitHub

Android Networking I: OkHttp, Volley and Gson

Android Volley完全解析(三),定製自己的Request

Android volley 解析(三)之文件上傳篇

Android OkHttp完全解析 是時候來了解OkHttp了

---------------------之前的回答分界線-----------------------

目前在開發一個項目,用的是Volley+OkHttp+Gson,感覺比之前用HttpURLConnection手擼爽到不知道哪裡去了,有空整理一下發個demo上來

ps:其他很多答案提到的Retrofit2,RxJava,Dagger2勾起了我極大的興趣,這周研究研究~


Volley + OkHttp作為網路請求框架,用起來棒棒噠


建議直接選用Retrofit2,

可以選擇結合RxJava,

再可以選擇結合RetroLambda

Retrofit2中默認內置了OkHttp來處理你的網路請求(當然也能換)

給兩篇文章題主可以參考下

Retrofit 2 主要講從Retrofit1.9升級到2.0的過程中會遇到的問題和區別,同時用一系列文章介紹了Retrofit的使用,題主可以結合著看,了解一下曾經的1.9,同時再看看現在的2.0。

給 Android 開發者的 RxJava 詳解 如果題主有興趣Retrofit結合RxJava,再可以參考這片文章,講解的非常詳細,即便不用也值得一看。文中也大致介紹了Retrofit和RxJava配合起來的效果。

Retrofit 這是官方文檔


可以嘗試一下volley!我們我們現在用的volley和fastjson封裝起來的,感覺還不錯!


可以用Retrofit


https://git.oschina.net/icecooly/FastHttpClient

推薦使用這個 封裝了一下 使用起來簡單一點


據說這是最完美當然model層

okhttp不難,建議看完api和帖子後,看看源碼有很多可以學習到的東西


可以考慮volley擴展okhttp,


Retrofit2+RxJava+Dagger2+Data Binding


可以自己進行二次封裝,參考Android 基於OkHttp的UI層回調封裝


SPDY和緩存響應、GZIP壓縮這塊

自己不斷研究代碼才是。學而時習之不亦說乎


推薦閱讀:

你遇到過哪些高質量的Android面試?
為什麼要學習 Android 開發?
Android Studio編譯慢、卡死和狂佔內存怎麼破?
為什麼就算配置很高的 Android 手機玩遊戲感覺畫面也沒有 iPhone 流暢,而且觸屏感覺比較遲鈍?

TAG:Android開發 |