国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 系統(tǒng) > Android > 正文

Android OkHttp的簡單使用和封裝詳解

2019-12-12 04:14:43
字體:
供稿:網(wǎng)友

Android OkHttp的簡單使用和封裝詳解

1,昨天把okHttp仔細的看了一下,以前都是調(diào)用同事封裝好了的網(wǎng)絡(luò)框架,直接使用很容易,但自己封裝卻不是那么簡單,還好,今天就來自我救贖一把,就和大家寫寫從最基礎(chǔ)的OKHttp的簡單get、post的使用,再到它的封裝。

2,OkHttp的簡單使用

  首先我們創(chuàng)建一個工程,并在布局文件中添加三個控件,TextView(用于展示獲取到j(luò)son后的信息)、Button(點擊開始請求網(wǎng)絡(luò))、ProgressBar(網(wǎng)絡(luò)加載提示框)

  ①簡單的異步Get請求

  第一步,創(chuàng)建OKHttpClient對象

  第二步,創(chuàng)建Request請求

  第三步,創(chuàng)建一個Call對象

  第四步,將請求添加到調(diào)度中

  不多說,直接上代碼:

//okHttp的基本使用 --- get方法  String url = "https://api.douban.com/v2/movie/top250?start=0&count=10";  //1,創(chuàng)建OKHttpClient對象  OkHttpClient mOkHttpClient = new OkHttpClient();  //2,創(chuàng)建一個Request  Request request = new Request.Builder().url(url).build();  //3,創(chuàng)建一個call對象  Call call = mOkHttpClient.newCall(request);  //4,將請求添加到調(diào)度中  call.enqueue(new Callback() {    @Override    public void onFailure(Request request, IOException e) {     }     @Override    public void onResponse(Response response) throws IOException {      if (response.isSuccessful()) {        final String message = response.body().string();        handler.post(new Runnable() {          @Override          public void run() {            tv_message.setText(message);            progressBar.setVisibility(View.GONE);          }        });       }    }   });

 效果如下: 

  

  注意,由于我們調(diào)用的enqueue()方法,是運行在網(wǎng)絡(luò)線程中的,所以當我們得到j(luò)son數(shù)據(jù)后想要獲取更新UI的話,可以開使用handle.post()方法在run方法里面更新UI。

  ② 簡單的異步Post請求

  這里的Post請求我們以最常見的注冊登錄來舉例。post請求的步驟和get是相似的只是在創(chuàng)建Request的 時候?qū)⒎?wù)器需要的參數(shù)傳遞進去.

  代碼如下:

String url = "http://192.168.1.123:8081/api/login";    //1,創(chuàng)建OKhttpClient對象    OkHttpClient mOkHttpClient = new OkHttpClient();    //2,創(chuàng)建Request    RequestBody formBody = new FormEncodingBuilder()        .add("username", "superadmin")        .add("pwd", "ba3253876aed6bc22d4a6ff53d8406c6ad864195ed144ab5c87621b6c233b548baeae6956df346ec8c17f5ea10f35ee3cbc514797ed7ddd3145464e2a0bab413")        .build();     Request request = new Request.Builder().url(url).post(formBody).build();    //3,創(chuàng)建call對象并將請求對象添加到調(diào)度中    mOkHttpClient.newCall(request).enqueue(new Callback() {      @Override      public void onFailure(Request request, IOException e) {       }       @Override      public void onResponse(Response response) throws IOException {        Log.i("wangjitao", response.body().string());      }    });

  看一下我們服務(wù)器的斷點

  

  可以看到我們服務(wù)器的確拿到了我們傳遞參數(shù),再看一下我們請求后拿到的數(shù)據(jù)

  ok,這樣的話我們的post方法就沒什么問題了

3,OkHttp的封裝

由于是封裝我們可以吧OKHttp和Gson給結(jié)合起來,那么我們在gradle文件添加以下的依賴

compile "com.squareup.okhttp:okhttp:2.4.0"compile 'com.squareup.okio:okio:1.5.0'compile "com.google.code.gson:gson:2.8.0"

  ①CallBack的創(chuàng)建  

  首選我們知道,當接口請求成功或者失敗的時候我們需要將這個信息通知給用戶,那么我們就需要創(chuàng)建一個抽象類RequestCallBack,請求前、成功、失敗、請求后這幾個方法,創(chuàng)建OnBefore()、OnAfter()、OnError()、OnResponse()對應(yīng)

/** * 在請求之前的方法,一般用于加載框展示 * * @param request */public void onBefore(Request request) {} /** * 在請求之后的方法,一般用于加載框隱藏 */public void onAfter() {} /** * 請求失敗的時候 * * @param request * @param e */public abstract void onError(Request request, Exception e); /** * * @param response */public abstract void onResponse(T response);

 由于我們每次想要的數(shù)據(jù)不一定,所以這里我們用<T>來接收想要裝成的數(shù)據(jù)格式,并通過反射得到想要的數(shù)據(jù)類型(一般是Bean、List)之類 ,所以RequestCallBack的整體代碼如下:

package com.qianmo.httprequest.http; import com.google.gson.internal.$Gson$Types;import com.squareup.okhttp.Request; import java.lang.reflect.ParameterizedType;import java.lang.reflect.Type;  /** * Created by wangjitao on 15/10/16. * 抽象類,用于請求成功后的回調(diào) */public abstract class ResultCallback<T> {  //這是請求數(shù)據(jù)的返回類型,包含常見的(Bean,List等)  Type mType;   public ResultCallback() {    mType = getSuperclassTypeParameter(getClass());  }   /**   * 通過反射想要的返回類型   *   * @param subclass   * @return   */  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]);  }   /**   * 在請求之前的方法,一般用于加載框展示   *   * @param request   */  public void onBefore(Request request) {  }   /**   * 在請求之后的方法,一般用于加載框隱藏   */  public void onAfter() {  }   /**   * 請求失敗的時候   *   * @param request   * @param e   */  public abstract void onError(Request request, Exception e);   /**   *   * @param response   */  public abstract void onResponse(T response);}

  ②對Get、Post方法的簡單封裝 

  首先我們創(chuàng)建一個OkHttpClientManager類,由于是管理類,所以,單例加靜態(tài)對象搞起

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

 在創(chuàng)建Manager對象的時候我們要把OkHttp的一些參數(shù)配置一下,順便一提一下,由于我們我們異步get、post方法是運行在子線程中,所以這里我們添加了分發(fā)的 Handler mDelivery;,重寫的OkHttpClientManager構(gòu)造方法如下:

private OkHttpClientManager() {    mOkHttpClient = new OkHttpClient();    mOkHttpClient.setConnectTimeout(10, TimeUnit.SECONDS);    mOkHttpClient.setWriteTimeout(10, TimeUnit.SECONDS);    mOkHttpClient.setReadTimeout(30, TimeUnit.SECONDS);    //cookie enabled    mOkHttpClient.setCookieHandler(new CookieManager(null, CookiePolicy.ACCEPT_ORIGINAL_SERVER));    mDelivery = new Handler(Looper.getMainLooper());    mGson = new Gson();  }

  前面的外部調(diào)用對象封裝好了,這里我們開始來封裝Get或Post方法,我這里以Post方法為例子,首先分析一下,post方法會有幾個參數(shù),參數(shù)一url,參數(shù)二參數(shù)params,參數(shù)三Callback(及我們上面的RequestCallBack)參數(shù)四flag(用于取消請求操作,可為空),基礎(chǔ)代碼如下:

/**    * 通用基礎(chǔ)的異步的post請求    * @param url    * @param callback    * @param tag    */    public void postAsyn(String url, Param[] params, final ResultCallback callback, Object tag) {      Request request = buildPostFormRequest(url, params, tag);      deliveryResult(callback, request);    }

  那么我們再看一下deliveryResult方法到底是干什么的

/**  * 請求回調(diào)處理方法并傳遞返回值  * @param callback Map類型請求參數(shù)  * @param request Request請求  */  private void deliveryResult(ResultCallback callback, Request request) {    if (callback == null)      callback = DEFAULT_RESULT_CALLBACK;    final ResultCallback resCallBack = callback;    //UI thread    callback.onBefore(request);    mOkHttpClient.newCall(request).enqueue(new Callback() {      @Override      public void onFailure(final Request request, final IOException e) {        sendFailedStringCallback(request, e, resCallBack);      }       @Override      public void onResponse(final Response response) {        try {          final String responseMessage=response.message();          final String responseBody = response.body().string();          if(response.code()==200){            if (resCallBack.mType == String.class) {              sendSuccessResultCallback(responseBody, resCallBack);            } else {              Object o = mGson.fromJson(responseBody, resCallBack.mType);              sendSuccessResultCallback(o, resCallBack);            }          }else{            Exception exception=new Exception(response.code()+":"+responseMessage);            sendFailedStringCallback(response.request(), exception, resCallBack);          }        } catch (IOException e) {          sendFailedStringCallback(response.request(), e, resCallBack);        } catch (com.google.gson.JsonParseException e) {//Json解析的錯誤          sendFailedStringCallback(response.request(), e, resCallBack);        }      }    });  }

  可以看到,這個方法主要是發(fā)出請求并對請求后的數(shù)據(jù)開始回調(diào),這樣我們就基本上封裝好了一個post方法了  ,把代碼這一部分的代碼貼出來看看

public class OkHttpClientManager {  private static final String TAG = "com.qianmo.httprequest.http.OkHttpClientManager";   private static OkHttpClientManager mInstance;  //默認的請求回調(diào)類  private final ResultCallback<String> DEFAULT_RESULT_CALLBACK = new ResultCallback<String>(){    @Override    public void onError(Request request, Exception e) {}     @Override    public void onResponse(String response) {}  };  private OkHttpClient mOkHttpClient;  private Handler mDelivery;  private Gson mGson;  private GetDelegate mGetDelegate = new GetDelegate();  private PostDelegate mPostDelegate = new PostDelegate();  private DownloadDelegate mDownloadDelegate = new DownloadDelegate();   private OkHttpClientManager() {    mOkHttpClient = new OkHttpClient();    mOkHttpClient.setConnectTimeout(10, TimeUnit.SECONDS);    mOkHttpClient.setWriteTimeout(10, TimeUnit.SECONDS);    mOkHttpClient.setReadTimeout(30, TimeUnit.SECONDS);    //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;  }   /**   * 外部可調(diào)用的Post異步請求方法   * @param url 請求url   * @param params   * @param callback 請求完成后回調(diào)類   */  public static void postAsyn(String url, Map<String, String> params, final ResultCallback callback) {    getInstance().getPostDelegate().postAsyn(url, params, callback, null);  }   /**     * 異步的post請求     * @param url     * @param params     * @param callback     * @param tag     */    public void postAsyn(String url, Map<String, String> params, final ResultCallback callback, Object tag) {      Param[] paramsArr = map2Params(params);      postAsyn(url, paramsArr, callback, tag);    }  /**     * 通用基礎(chǔ)的異步的post請求     * @param url     * @param callback     * @param tag     */    public void postAsyn(String url, Param[] params, final ResultCallback callback, Object tag) {      Request request = buildPostFormRequest(url, params, tag);      deliveryResult(callback, request);    }     /**   * 請求回調(diào)處理方法并傳遞返回值   * @param callback Map類型請求參數(shù)   * @param request Request請求   */  private void deliveryResult(ResultCallback callback, Request request) {    if (callback == null)      callback = DEFAULT_RESULT_CALLBACK;    final ResultCallback resCallBack = callback;    //UI thread    callback.onBefore(request);    mOkHttpClient.newCall(request).enqueue(new Callback() {      @Override      public void onFailure(final Request request, final IOException e) {        sendFailedStringCallback(request, e, resCallBack);      }       @Override      public void onResponse(final Response response) {        try {          final String responseMessage=response.message();          final String responseBody = response.body().string();          if(response.code()==200){            if (resCallBack.mType == String.class) {              sendSuccessResultCallback(responseBody, resCallBack);            } else {              Object o = mGson.fromJson(responseBody, resCallBack.mType);              sendSuccessResultCallback(o, resCallBack);            }          }else{            Exception exception=new Exception(response.code()+":"+responseMessage);            sendFailedStringCallback(response.request(), exception, resCallBack);          }        } catch (IOException e) {          sendFailedStringCallback(response.request(), e, resCallBack);        } catch (com.google.gson.JsonParseException e) {//Json解析的錯誤          sendFailedStringCallback(response.request(), e, resCallBack);        }      }    });  }   /**   * 處理請求成功的回調(diào)信息方法   * @param object 服務(wù)器響應(yīng)信息   * @param callback 回調(diào)類   */  private void sendSuccessResultCallback(final Object object, final   ResultCallback callback) {    mDelivery.post(() -> {      callback.onResponse(object);      callback.onAfter();    });  }}  

  這樣我們就把Post方法封裝好了,同理Get方法,ok,現(xiàn)在我們可以來調(diào)用調(diào)用了,在調(diào)用之前我們可以對返回數(shù)據(jù)格式再來封裝封裝,一般我們后臺返回的數(shù)據(jù)格式是類似如下:

{ "code": 200, "data": {}, "message": "登錄成功"}

 而data中有可能是對象,也有可能是數(shù)組,所以我們用兩個類來實現(xiàn)一下

 CommonResultBean

package com.qianmo.httprequest.bean; /** * 服務(wù)端返回通用接收實體 * Created by wangjitao on 15/10/30. */public class CommonResultBean<T> {  private String code;  private T data;  private String message;   public String getCode() {    return code;  }   public void setCode(String code) {    this.code = code;  }   public T getData() {    return data;  }   public void setData(T data) {    this.data = data;  }   public String getMessage() {    return message;  }   public void setMessage(String message) {    this.message = message;  }}

 CommonResultListBean

package com.qianmo.httprequest.bean; import java.util.List; /** * 服務(wù)端返回帶有List數(shù)據(jù)的通用接收實體 * Created by wangjitao on 15/12/1. */public class CommonResultListBean<T> {  private String code;  private List<T> data;  private String message;   public String getCode() {    return code;  }   public void setCode(String code) {    this.code = code;  }   public List<T> getData() {    return data;  }   public void setData(List<T> data) {    this.data = data;  }   public String getMessage() {    return message;  }   public void setMessage(String message) {    this.message = message;  }}

  ok,現(xiàn)在還是以上面我們登錄的接口為例子開始我們的方法調(diào)用,返回的數(shù)據(jù)格式如圖所示

  我們創(chuàng)建UserMenu.java類

package com.qianmo.httprequest.bean; import java.util.List; /** * Created by wangjitao on 2016/12/21 0021. * E-Mail:543441727@qq.com * 用戶菜單權(quán)限按鈕 */public class UserMenu {   /**   * last_login_time : 2016-12-21 15:40:28   * member_id : 1   * modules : []   * phone : 18900532225   * real_name : 超級管理員   * role : {"role_id":1,"role_name":"超級管理員"}   * username : superadmin   */   private String last_login_time;  private int member_id;  private String phone;  private String real_name;  /**   * role_id : 1   * role_name : 超級管理員   */   private RoleBean role;  private String username;  /**   * module_code : 100   * module_id : 1   * module_name : 首頁   * pid : 0   * type : 1   * value : P_index   */   private List<ModulesBean> modules;   public String getLast_login_time() {    return last_login_time;  }   public void setLast_login_time(String last_login_time) {    this.last_login_time = last_login_time;  }   public int getMember_id() {    return member_id;  }   public void setMember_id(int member_id) {    this.member_id = member_id;  }   public String getPhone() {    return phone;  }   public void setPhone(String phone) {    this.phone = phone;  }   public String getReal_name() {    return real_name;  }   public void setReal_name(String real_name) {    this.real_name = real_name;  }   public RoleBean getRole() {    return role;  }   public void setRole(RoleBean role) {    this.role = role;  }   public String getUsername() {    return username;  }   public void setUsername(String username) {    this.username = username;  }   public List<ModulesBean> getModules() {    return modules;  }   public void setModules(List<ModulesBean> modules) {    this.modules = modules;  }   public static class RoleBean {    private int role_id;    private String role_name;     public int getRole_id() {      return role_id;    }     public void setRole_id(int role_id) {      this.role_id = role_id;    }     public String getRole_name() {      return role_name;    }     public void setRole_name(String role_name) {      this.role_name = role_name;    }  }   public static class ModulesBean {    private String module_code;    private int module_id;    private String module_name;    private int pid;    private int type;    private String value;     public String getModule_code() {      return module_code;    }     public void setModule_code(String module_code) {      this.module_code = module_code;    }     public int getModule_id() {      return module_id;    }     public void setModule_id(int module_id) {      this.module_id = module_id;    }     public String getModule_name() {      return module_name;    }     public void setModule_name(String module_name) {      this.module_name = module_name;    }     public int getPid() {      return pid;    }     public void setPid(int pid) {      this.pid = pid;    }     public int getType() {      return type;    }     public void setType(int type) {      this.type = type;    }     public String getValue() {      return value;    }     public void setValue(String value) {      this.value = value;    }  } }

  所以MainActivity代碼如下:

package com.qianmo.httprequest; import android.os.Environment;import android.os.Handler;import android.support.v7.app.AppCompatActivity;import android.os.Bundle;import android.util.Log;import android.view.View;import android.view.View.OnClickListener;import android.widget.Button;import android.widget.ProgressBar;import android.widget.TextView; import com.qianmo.httprequest.bean.CommonResultBean;import com.qianmo.httprequest.bean.UserMenu;import com.qianmo.httprequest.http.IRequestCallBack;import com.qianmo.httprequest.http.IRequestManager;import com.qianmo.httprequest.http.OkHttpClientManager;import com.qianmo.httprequest.http.RequestFactory;import com.qianmo.httprequest.http.ResultCallback;import com.squareup.okhttp.Call;import com.squareup.okhttp.Callback;import com.squareup.okhttp.FormEncodingBuilder;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.IOException;import java.util.HashMap;import java.util.Map;  public class MainActivity extends AppCompatActivity implements OnClickListener {  private Handler handler;  private TextView tv_message;  private Button btn_login;  private ProgressBar progressBar;   @Override  protected void onCreate(Bundle savedInstanceState) {    super.onCreate(savedInstanceState);    setContentView(R.layout.activity_main);    tv_message = (TextView) findViewById(R.id.tv_message);    btn_login = (Button) findViewById(R.id.btn_login);    progressBar = (ProgressBar) findViewById(R.id.progressBar);    handler = new Handler();    btn_login.setOnClickListener(this);  }   @Override  public void onClick(View view) {    progressBar.setVisibility(View.VISIBLE);      String url = "http://192.168.1.123:8081/api/login";    Map<String, String> params = new HashMap();    params.put("username", "superadmin");    params.put("pwd", "ba3253876aed6bc22d4a6ff53d8406c6ad864195ed144ab5c87621b6c233b548baeae6956df346ec8c17f5ea10f35ee3cbc514797ed7ddd3145464e2a0bab413");    OkHttpClientManager.postAsyn(url, params,        new ResultCallback<CommonResultBean<UserMenu>>() {          @Override          public void onError(Request request, Exception e) {           }           @Override          public void onResponse(CommonResultBean<UserMenu> response) {            if (response.getData() != null) {              UserMenu userMenu = response.getData();              tv_message.setText(userMenu.getReal_name());              progressBar.setVisibility(View.GONE);            }          }        });   }}

  這樣我們就可以簡單的調(diào)用了,最后看一下我們的效果:

 See You Next Time???

 感謝閱讀,希望能幫助到大家,謝謝大家對本站的支持!

發(fā)表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發(fā)表
主站蜘蛛池模板: 盐山县| 邵东县| 东安县| 拉萨市| 遵义市| 诏安县| 海伦市| 易门县| 江西省| 松阳县| 宣汉县| 肃宁县| 泽州县| 房产| 偃师市| 江永县| 沐川县| 临沧市| 青田县| 武乡县| 左云县| 阳城县| 上林县| 当涂县| 嘉义县| 利川市| 大化| 高唐县| 达日县| 阜城县| 南漳县| 洛川县| 酒泉市| 金堂县| 法库县| 新龙县| 建昌县| 于都县| 大邑县| 宽甸| 临汾市|