Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> 詳解Android OkHttp完全解析

詳解Android OkHttp完全解析

編輯:關於Android編程

一、概述

最近在群裡聽到各種討論okhttp的話題,可見okhttp的口碑相當好了。再加上Google貌似在6.0版本裡面刪除了HttpClient相關API,對於這個行為不做評價。為了更好的在應對網絡訪問,學習下okhttp還是蠻必要的,本篇博客首先介紹okhttp的簡單使用,主要包含:

  • 一般的get請求
  • 一般的post請求
  • 基於Http的文件上傳
  • 文件下載
  • 加載圖片
  • 支持請求回調,直接返回對象、對象集合
  • 支持session的保持

最後會對上述幾個功能進行封裝,完整的封裝類的地址見:http://xiazai.jb51.net/201611/yuanma/okhttputils-master_jb51.zip

使用前,對於Android Studio的用戶,可以選擇添加:
compile 'com.squareup.okhttp:okhttp:2.4.0'
或者Eclipse的用戶,可以下載最新的jarokhttp he latest JAR ,添加依賴就可以用了。

注意:okhttp內部依賴okio,別忘了同時導入okio:

gradle: compile 'com.squareup.okio:okio:1.5.0'

最新的jar地址:okio the latest JAR

二、使用教程

(一)Http Get

對了網絡加載庫,那麼最常見的肯定就是http get請求了,比如獲取一個網頁的內容。

//創建okHttpClient對象
OkHttpClient mOkHttpClient = new OkHttpClient();
//創建一個Request
final Request request = new Request.Builder()
    .url("https://github.com/hongyangAndroid")
    .build();
//new call
Call call = mOkHttpClient.newCall(request); 
//請求加入調度
call.enqueue(new Callback()
  {
   @Override
   public void onFailure(Request request, IOException e)
   {
   }

   @Override
   public void onResponse(final Response response) throws IOException
   {
     //String htmlStr = response.body().string();
   }
  });   

1.以上就是發送一個get請求的步驟,首先構造一個Request對象,參數最起碼有個url,當然你可以通過Request.Builder設置更多的參數比如:header、method等。

2.然後通過request的對象去構造得到一個Call對象,類似於將你的請求封裝成了任務,既然是任務,就會有execute()和cancel()等方法。

3.最後,我們希望以異步的方式去執行請求,所以我們調用的是call.enqueue,將call加入調度隊列,然後等待任務執行完成,我們在Callback中即可得到結果。

看到這,你會發現,整體的寫法還是比較長的,所以封裝肯定是要做的,不然每個請求這麼寫,得累死。

ok,需要注意幾點:

1、onResponse回調的參數是response,一般情況下,比如我們希望獲得返回的字符串,可以通過response.body().string()獲取;如果希望獲得返回的二進制字節數組,則調用response.body().bytes();如果你想拿到返回的inputStream,則調用response.body().byteStream()

看到這,你可能會奇怪,竟然還能拿到返回的inputStream,看到這個最起碼能意識到一點,這裡支持大文件下載,有inputStream我們就可以通過IO的方式寫文件。不過也說明一個問題,這個onResponse執行的線程並不是UI線程。的確是的,如果你希望操作控件,還是需要使用handler等,例如:

@Override
public void onResponse(final Response response) throws IOException
{
  final String res = response.body().string();
  runOnUiThread(new Runnable()
  {
   @Override
   public void run()
   {
   mTv.setText(res);
   }

  });
}

2、我們這裡是異步的方式去執行,當然也支持阻塞的方式,上面我們也說了Call有一個execute()方法,你也可以直接調用call.execute()通過返回一個Response。

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

(二) Http Post 攜帶參數

看來上面的簡單的get請求,基本上整個的用法也就掌握了,比如post攜帶參數,也僅僅是Request的構造的不同。

Request request = buildMultipartFormRequest(
  url, new File[]{file}, new String[]{fileKey}, null);
FormEncodingBuilder builder = new FormEncodingBuilder(); 
builder.add("username","張鴻洋");

Request request = new Request.Builder()
     .url(url)
    .post(builder.build())
    .build();
 mOkHttpClient.newCall(request).enqueue(new Callback(){});

大家都清楚,post的時候,參數是包含在請求體中的;所以我們通過FormEncodingBuilder。添加多個String鍵值對,然後去構造RequestBody,最後完成我們Request的構造。

後面的就和上面一樣了。

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

(三)基於Http的文件上傳

接下來我們在介紹一個可以構造RequestBody的Builder,叫做MultipartBuilder。當我們需要做類似於表單上傳的時候,就可以使用它來構造我們的requestBody。

File file = new File(Environment.getExternalStorageDirectory(), "balabala.mp4");

RequestBody fileBody = RequestBody.create(MediaType.parse("application/octet-stream"), file);

RequestBody requestBody = new MultipartBuilder()
  .type(MultipartBuilder.FORM)
  .addPart(Headers.of(
   "Content-Disposition", 
    "form-data; name=\"username\""), 
   RequestBody.create(null, "張鴻洋"))
  .addPart(Headers.of(
   "Content-Disposition", 
   "form-data; name=\"mFile\"; 
   filename=\"wjd.mp4\""), fileBody)
  .build();

Request request = new Request.Builder()
 .url("http://192.168.1.103:8080/okHttpServer/fileUpload")
 .post(requestBody)
 .build();

Call call = mOkHttpClient.newCall(request);
call.enqueue(new Callback()
{
 //...
});

上述代碼向服務器傳遞了一個鍵值對username:張鴻洋和一個文件。我們通過MultipartBuilder的addPart方法可以添加鍵值對或者文件。

其實類似於我們拼接模擬浏覽器行為的方式,如果你對這塊不了解,可以參考:從原理角度解析Android (Java) http 文件上傳

ok,對於我們最開始的目錄還剩下圖片下載,文件下載;這兩個一個是通過回調的Response拿到byte[]然後decode成圖片;文件下載,就是拿到inputStream做寫文件操作,我們這裡就不贅述了。

接下來我們主要看如何封裝上述的代碼。

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

三、封裝

由於按照上述的代碼,寫多個請求肯定包含大量的重復代碼,所以我希望封裝後的代碼調用是這樣的:

(一)使用

1.一般的get請求

OkHttpClientManager.getAsyn("https://www.baidu.com", new OkHttpClientManager.ResultCallback<String>()
  {
   @Override
   public void onError(Request request, Exception e)
   {
    e.printStackTrace();
   }

   @Override
   public void onResponse(String u)
   {
    mTv.setText(u);//注意這裡是UI線程
   }
  });

對於一般的請求,我們希望給個url,然後CallBack裡面直接操作控件。

2.文件上傳且攜帶參數

我們希望提供一個方法,傳入url,params,file,callback即可。

 OkHttpClientManager.postAsyn("http://192.168.1.103:8080/okHttpServer/fileUpload",//
 new OkHttpClientManager.ResultCallback<String>()
 {
  @Override
  public void onError(Request request, IOException e)
  {
   e.printStackTrace();
  }

  @Override
  public void onResponse(String result)
  {

  }
 },//
 file,//
 "mFile",//
 new OkHttpClientManager.Param[]{
   new OkHttpClientManager.Param("username", "zhy"),
   new OkHttpClientManager.Param("password", "123")}
  );



鍵值對沒什麼說的,參數3為file,參數4為file對應的name,這個name不是文件的名字;
 對應於http中的

<input type="file" name="mFile" > 

對應的是name後面的值,即mFile.

3.文件下載

對於文件下載,提供url,目標dir,callback即可。

OkHttpClientManager.downloadAsyn(
 "http://192.168.1.103:8080/okHttpServer/files/messenger_01.png", 
 Environment.getExternalStorageDirectory().getAbsolutePath(), 
new OkHttpClientManager.ResultCallback<String>()
 {
  @Override
  public void onError(Request request, IOException e)
  {

  }

  @Override
  public void onResponse(String response)
  {
   //文件下載成功,這裡回調的reponse為文件的absolutePath
  }
});

4.展示圖片

展示圖片,我們希望提供一個url和一個imageview,如果下載成功,直接幫我們設置上即可。

OkHttpClientManager.displayImage(mImageView, 
  http://images.csdn.net/20150817/1.jpg);

內部會自動根據imageview的大小自動對圖片進行合適的壓縮。雖然,這裡可能不適合一次性加載大量圖片的場景,但是對於app中偶爾有幾個圖片的加載,還是可用的。

四、整合Json

很多人提出項目中使用時,服務端返回的是Json字符串,希望客戶端回調可以直接拿到對象,於是整合進入了json,完善該功能。

(一)直接回調對象

例如現在有個User實體類:

package com.zhy.utils.http.okhttp;

public class User {

 public String username ; 
 public String password ;

 public User() {
  // TODO Auto-generated constructor stub
 }

 public User(String username, String password) {
  this.username = username;
  this.password = password;
 }

 @Override
 public String toString()
 {
  return "User{" +
    "username='" + username + '\'' +
    ", password='" + password + '\'' +
    '}';
 }
}

服務端返回:

{"username":"zhy","password":"123"}

客戶端可以如下方式調用:

 OkHttpClientManager.getAsyn("http://192.168.56.1:8080/okHttpServer/user!getUser",
new OkHttpClientManager.ResultCallback<User>()
{
 @Override
 public void onError(Request request, Exception e)
 {
  e.printStackTrace();
 }

 @Override
 public void onResponse(User user)
 {
  mTv.setText(u.toString());//UI線程
 }
});

我們傳入泛型User,在onResponse裡面直接回調User對象。 

 這裡特別要注意的事,如果在json字符串->實體對象過程中發生錯誤,程序不會崩潰,onError方法會被回調。

注意:這裡做了少許的更新,接口命名從StringCallback修改為ResultCallback。接口中的onFailure方法修改為onError。

(二) 回調對象集合

依然是上述的User類,服務端返回

[{"username":"zhy","password":"123"},{"username":"lmj","password":"12345"}]

則客戶端可以如下調用:

OkHttpClientManager.getAsyn("http://192.168.56.1:8080/okHttpServer/user!getUsers",
new OkHttpClientManager.ResultCallback<List<User>>()
{
 @Override
 public void onError(Request request, Exception e)
 {
  e.printStackTrace();
 }
 @Override
 public void onResponse(List<User> us)
 {
  Log.e("TAG", us.size() + "");
  mTv.setText(us.get(1).toString());
 }
});

唯一的區別,就是泛型變為List<User> ,ok , 如果發現bug或者有任何意見歡迎留言。

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

源碼

ok,基本介紹完了,對於封裝的代碼其實也很簡單,我就直接貼出來了,因為也沒什麼好介紹的,如果你看完上面的用法,肯定可以看懂:

package com.zhy.utils.http.okhttp;

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Handler;
import android.os.Looper;
import android.widget.ImageView;

import com.google.gson.Gson;
import com.google.gson.internal.$Gson$Types;
import com.squareup.okhttp.Call;
import com.squareup.okhttp.Callback;
import com.squareup.okhttp.FormEncodingBuilder;
import com.squareup.okhttp.Headers;
import com.squareup.okhttp.MediaType;
import com.squareup.okhttp.MultipartBuilder;
import com.squareup.okhttp.OkHttpClient;
import com.squareup.okhttp.Request;
import com.squareup.okhttp.RequestBody;
import com.squareup.okhttp.Response;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.net.CookieManager;
import java.net.CookiePolicy;
import java.net.FileNameMap;
import java.net.URLConnection;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

/**
 * Created by zhy on 15/8/17.
 */
public class OkHttpClientManager
{
 private static OkHttpClientManager mInstance;
 private OkHttpClient mOkHttpClient;
 private Handler mDelivery;
 private Gson mGson;


 private static final String TAG = "OkHttpClientManager";

 private OkHttpClientManager()
 {
  mOkHttpClient = new OkHttpClient();
  //cookie enabled
  mOkHttpClient.setCookieHandler(new CookieManager(null, CookiePolicy.ACCEPT_ORIGINAL_SERVER));
  mDelivery = new Handler(Looper.getMainLooper());
  mGson = new Gson();
 }

 public static OkHttpClientManager getInstance()
 {
  if (mInstance == null)
  {
   synchronized (OkHttpClientManager.class)
   {
    if (mInstance == null)
    {
     mInstance = new OkHttpClientManager();
    }
   }
  }
  return mInstance;
 }

 /**
  * 同步的Get請求
  *
  * @param url
  * @return Response
  */
 private Response _getAsyn(String url) throws IOException
 {
  final Request request = new Request.Builder()
    .url(url)
    .build();
  Call call = mOkHttpClient.newCall(request);
  Response execute = call.execute();
  return execute;
 }

 /**
  * 同步的Get請求
  *
  * @param url
  * @return 字符串
  */
 private String _getAsString(String url) throws IOException
 {
  Response execute = _getAsyn(url);
  return execute.body().string();
 }


 /**
  * 異步的get請求
  *
  * @param url
  * @param callback
  */
 private void _getAsyn(String url, final ResultCallback callback)
 {
  final Request request = new Request.Builder()
    .url(url)
    .build();
  deliveryResult(callback, request);
 }


 /**
  * 同步的Post請求
  *
  * @param url
  * @param params post的參數
  * @return
  */
 private Response _post(String url, Param... params) throws IOException
 {
  Request request = buildPostRequest(url, params);
  Response response = mOkHttpClient.newCall(request).execute();
  return response;
 }


 /**
  * 同步的Post請求
  *
  * @param url
  * @param params post的參數
  * @return 字符串
  */
 private String _postAsString(String url, Param... params) throws IOException
 {
  Response response = _post(url, params);
  return response.body().string();
 }

 /**
  * 異步的post請求
  *
  * @param url
  * @param callback
  * @param params
  */
 private void _postAsyn(String url, final ResultCallback callback, Param... params)
 {
  Request request = buildPostRequest(url, params);
  deliveryResult(callback, request);
 }

 /**
  * 異步的post請求
  *
  * @param url
  * @param callback
  * @param params
  */
 private void _postAsyn(String url, final ResultCallback callback, Map<String, String> params)
 {
  Param[] paramsArr = map2Params(params);
  Request request = buildPostRequest(url, paramsArr);
  deliveryResult(callback, request);
 }

 /**
  * 同步基於post的文件上傳
  *
  * @param params
  * @return
  */
 private Response _post(String url, File[] files, String[] fileKeys, Param... params) throws IOException
 {
  Request request = buildMultipartFormRequest(url, files, fileKeys, params);
  return mOkHttpClient.newCall(request).execute();
 }

 private Response _post(String url, File file, String fileKey) throws IOException
 {
  Request request = buildMultipartFormRequest(url, new File[]{file}, new String[]{fileKey}, null);
  return mOkHttpClient.newCall(request).execute();
 }

 private Response _post(String url, File file, String fileKey, Param... params) throws IOException
 {
  Request request = buildMultipartFormRequest(url, new File[]{file}, new String[]{fileKey}, params);
  return mOkHttpClient.newCall(request).execute();
 }

 /**
  * 異步基於post的文件上傳
  *
  * @param url
  * @param callback
  * @param files
  * @param fileKeys
  * @throws IOException
  */
 private void _postAsyn(String url, ResultCallback callback, File[] files, String[] fileKeys, Param... params) throws IOException
 {
  Request request = buildMultipartFormRequest(url, files, fileKeys, params);
  deliveryResult(callback, request);
 }

 /**
  * 異步基於post的文件上傳,單文件不帶參數上傳
  *
  * @param url
  * @param callback
  * @param file
  * @param fileKey
  * @throws IOException
  */
 private void _postAsyn(String url, ResultCallback callback, File file, String fileKey) throws IOException
 {
  Request request = buildMultipartFormRequest(url, new File[]{file}, new String[]{fileKey}, null);
  deliveryResult(callback, request);
 }

 /**
  * 異步基於post的文件上傳,單文件且攜帶其他form參數上傳
  *
  * @param url
  * @param callback
  * @param file
  * @param fileKey
  * @param params
  * @throws IOException
  */
 private void _postAsyn(String url, ResultCallback callback, File file, String fileKey, Param... params) throws IOException
 {
  Request request = buildMultipartFormRequest(url, new File[]{file}, new String[]{fileKey}, params);
  deliveryResult(callback, request);
 }

 /**
  * 異步下載文件
  *
  * @param url
  * @param destFileDir 本地文件存儲的文件夾
  * @param callback
  */
 private void _downloadAsyn(final String url, final String destFileDir, final ResultCallback callback)
 {
  final Request request = new Request.Builder()
    .url(url)
    .build();
  final Call call = mOkHttpClient.newCall(request);
  call.enqueue(new Callback()
  {
   @Override
   public void onFailure(final Request request, final IOException e)
   {
    sendFailedStringCallback(request, e, callback);
   }

   @Override
   public void onResponse(Response response)
   {
    InputStream is = null;
    byte[] buf = new byte[2048];
    int len = 0;
    FileOutputStream fos = null;
    try
    {
     is = response.body().byteStream();
     File file = new File(destFileDir, getFileName(url));
     fos = new FileOutputStream(file);
     while ((len = is.read(buf)) != -1)
     {
      fos.write(buf, 0, len);
     }
     fos.flush();
     //如果下載文件成功,第一個參數為文件的絕對路徑
     sendSuccessResultCallback(file.getAbsolutePath(), callback);
    } catch (IOException e)
    {
     sendFailedStringCallback(response.request(), e, callback);
    } finally
    {
     try
     {
      if (is != null) is.close();
     } catch (IOException e)
     {
     }
     try
     {
      if (fos != null) fos.close();
     } catch (IOException e)
     {
     }
    }

   }
  });
 }

 private String getFileName(String path)
 {
  int separatorIndex = path.lastIndexOf("/");
  return (separatorIndex < 0) ? path : path.substring(separatorIndex + 1, path.length());
 }

 /**
  * 加載圖片
  *
  * @param view
  * @param url
  * @throws IOException
  */
 private void _displayImage(final ImageView view, final String url, final int errorResId)
 {
  final Request request = new Request.Builder()
    .url(url)
    .build();
  Call call = mOkHttpClient.newCall(request);
  call.enqueue(new Callback()
  {
   @Override
   public void onFailure(Request request, IOException e)
   {
    setErrorResId(view, errorResId);
   }

   @Override
   public void onResponse(Response response)
   {
    InputStream is = null;
    try
    {
     is = response.body().byteStream();
     ImageUtils.ImageSize actualImageSize = ImageUtils.getImageSize(is);
     ImageUtils.ImageSize imageViewSize = ImageUtils.getImageViewSize(view);
     int inSampleSize = ImageUtils.calculateInSampleSize(actualImageSize, imageViewSize);
     try
     {
      is.reset();
     } catch (IOException e)
     {
      response = _getAsyn(url);
      is = response.body().byteStream();
     }

     BitmapFactory.Options ops = new BitmapFactory.Options();
     ops.inJustDecodeBounds = false;
     ops.inSampleSize = inSampleSize;
     final Bitmap bm = BitmapFactory.decodeStream(is, null, ops);
     mDelivery.post(new Runnable()
     {
      @Override
      public void run()
      {
       view.setImageBitmap(bm);
      }
     });
    } catch (Exception e)
    {
     setErrorResId(view, errorResId);

    } finally
    {
     if (is != null) try
     {
      is.close();
     } catch (IOException e)
     {
      e.printStackTrace();
     }
    }
   }
  });


 }

 private void setErrorResId(final ImageView view, final int errorResId)
 {
  mDelivery.post(new Runnable()
  {
   @Override
   public void run()
   {
    view.setImageResource(errorResId);
   }
  });
 }


 //*************對外公布的方法************


 public static Response getAsyn(String url) throws IOException
 {
  return getInstance()._getAsyn(url);
 }


 public static String getAsString(String url) throws IOException
 {
  return getInstance()._getAsString(url);
 }

 public static void getAsyn(String url, ResultCallback callback)
 {
  getInstance()._getAsyn(url, callback);
 }

 public static Response post(String url, Param... params) throws IOException
 {
  return getInstance()._post(url, params);
 }

 public static String postAsString(String url, Param... params) throws IOException
 {
  return getInstance()._postAsString(url, params);
 }

 public static void postAsyn(String url, final ResultCallback callback, Param... params)
 {
  getInstance()._postAsyn(url, callback, params);
 }


 public static void postAsyn(String url, final ResultCallback callback, Map<String, String> params)
 {
  getInstance()._postAsyn(url, callback, params);
 }


 public static Response post(String url, File[] files, String[] fileKeys, Param... params) throws IOException
 {
  return getInstance()._post(url, files, fileKeys, params);
 }

 public static Response post(String url, File file, String fileKey) throws IOException
 {
  return getInstance()._post(url, file, fileKey);
 }

 public static Response post(String url, File file, String fileKey, Param... params) throws IOException
 {
  return getInstance()._post(url, file, fileKey, params);
 }

 public static void postAsyn(String url, ResultCallback callback, File[] files, String[] fileKeys, Param... params) throws IOException
 {
  getInstance()._postAsyn(url, callback, files, fileKeys, params);
 }


 public static void postAsyn(String url, ResultCallback callback, File file, String fileKey) throws IOException
 {
  getInstance()._postAsyn(url, callback, file, fileKey);
 }


 public static void postAsyn(String url, ResultCallback callback, File file, String fileKey, Param... params) throws IOException
 {
  getInstance()._postAsyn(url, callback, file, fileKey, params);
 }

 public static void displayImage(final ImageView view, String url, int errorResId) throws IOException
 {
  getInstance()._displayImage(view, url, errorResId);
 }


 public static void displayImage(final ImageView view, String url)
 {
  getInstance()._displayImage(view, url, -1);
 }

 public static void downloadAsyn(String url, String destDir, ResultCallback callback)
 {
  getInstance()._downloadAsyn(url, destDir, callback);
 }

 //****************************


 private Request buildMultipartFormRequest(String url, File[] files,
            String[] fileKeys, Param[] params)
 {
  params = validateParam(params);

  MultipartBuilder builder = new MultipartBuilder()
    .type(MultipartBuilder.FORM);

  for (Param param : params)
  {
   builder.addPart(Headers.of("Content-Disposition", "form-data; name=\"" + param.key + "\""),
     RequestBody.create(null, param.value));
  }
  if (files != null)
  {
   RequestBody fileBody = null;
   for (int i = 0; i < files.length; i++)
   {
    File file = files[i];
    String fileName = file.getName();
    fileBody = RequestBody.create(MediaType.parse(guessMimeType(fileName)), file);
    //TODO 根據文件名設置contentType
    builder.addPart(Headers.of("Content-Disposition",
        "form-data; name=\"" + fileKeys[i] + "\"; filename=\"" + fileName + "\""),
      fileBody);
   }
  }

  RequestBody requestBody = builder.build();
  return new Request.Builder()
    .url(url)
    .post(requestBody)
    .build();
 }

 private String guessMimeType(String path)
 {
  FileNameMap fileNameMap = URLConnection.getFileNameMap();
  String contentTypeFor = fileNameMap.getContentTypeFor(path);
  if (contentTypeFor == null)
  {
   contentTypeFor = "application/octet-stream";
  }
  return contentTypeFor;
 }


 private Param[] validateParam(Param[] params)
 {
  if (params == null)
   return new Param[0];
  else return params;
 }

 private Param[] map2Params(Map<String, String> params)
 {
  if (params == null) return new Param[0];
  int size = params.size();
  Param[] res = new Param[size];
  Set<Map.Entry<String, String>> entries = params.entrySet();
  int i = 0;
  for (Map.Entry<String, String> entry : entries)
  {
   res[i++] = new Param(entry.getKey(), entry.getValue());
  }
  return res;
 }

 private static final String SESSION_KEY = "Set-Cookie";
 private static final String mSessionKey = "JSESSIONID";

 private Map<String, String> mSessions = new HashMap<String, String>();

 private void deliveryResult(final ResultCallback callback, Request request)
 {
  mOkHttpClient.newCall(request).enqueue(new Callback()
  {
   @Override
   public void onFailure(final Request request, final IOException e)
   {
    sendFailedStringCallback(request, e, callback);
   }

   @Override
   public void onResponse(final Response response)
   {
    try
    {
     final String string = response.body().string();
     if (callback.mType == String.class)
     {
      sendSuccessResultCallback(string, callback);
     } else
     {
      Object o = mGson.fromJson(string, callback.mType);
      sendSuccessResultCallback(o, callback);
     }


    } catch (IOException e)
    {
     sendFailedStringCallback(response.request(), e, callback);
    } catch (com.google.gson.JsonParseException e)//Json解析的錯誤
    {
     sendFailedStringCallback(response.request(), e, callback);
    }

   }
  });
 }

 private void sendFailedStringCallback(final Request request, final Exception e, final ResultCallback callback)
 {
  mDelivery.post(new Runnable()
  {
   @Override
   public void run()
   {
    if (callback != null)
     callback.onError(request, e);
   }
  });
 }

 private void sendSuccessResultCallback(final Object object, final ResultCallback callback)
 {
  mDelivery.post(new Runnable()
  {
   @Override
   public void run()
   {
    if (callback != null)
    {
     callback.onResponse(object);
    }
   }
  });
 }

 private Request buildPostRequest(String url, Param[] params)
 {
  if (params == null)
  {
   params = new Param[0];
  }
  FormEncodingBuilder builder = new FormEncodingBuilder();
  for (Param param : params)
  {
   builder.add(param.key, param.value);
  }
  RequestBody requestBody = builder.build();
  return new Request.Builder()
    .url(url)
    .post(requestBody)
    .build();
 }


 public static abstract class ResultCallback<T>
 {
  Type mType;

  public ResultCallback()
  {
   mType = getSuperclassTypeParameter(getClass());
  }

  static Type getSuperclassTypeParameter(Class<?> subclass)
  {
   Type superclass = subclass.getGenericSuperclass();
   if (superclass instanceof Class)
   {
    throw new RuntimeException("Missing type parameter.");
   }
   ParameterizedType parameterized = (ParameterizedType) superclass;
   return $Gson$Types.canonicalize(parameterized.getActualTypeArguments()[0]);
  }

  public abstract void onError(Request request, Exception e);

  public abstract void onResponse(T response);
 }

 public static class Param
 {
  public Param()
  {
  }

  public Param(String key, String value)
  {
   this.key = key;
   this.value = value;
  }

  String key;
  String value;
 }


}

源碼地址:demo下載http://xiazai.jb51.net/201611/yuanma/okhttputils-master_jb51.zip
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持本站。

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved