Android網路請求三方庫OkHttp,Retrofit的使用,及其註解使用的簡介
阿新 • • 發佈:2019-01-24
工作內容:
1.OkHttp的Post,Get請求
2.Retrofit的使用【更多詳情可以參考】
學習分享:[程式碼中使用了ButterKnife,參考ButterKnife使用]
1.OkHttp的使用步驟【注意同步載入最好放入子執行緒中:同步載入call.execute,非同步載入call.enqueue】
使用OkHttp注意:
1.同步載入最好放入子執行緒中(網路請求很可能耗時過長導致出錯)
2.一個onResponse方法中response.body().string()只能使用一次(可以定義1個String變數接受它的值,重複使用)
① 新增依賴
compile 'com.squareup.okhttp3:okhttp:3.4.1'
② 使用步驟如下:
1.定義規範介面
import okhttp3.Call;
/**
* Created by Administrator on 2016/9/27.
* 介面:用於規範OkHttp請求的方法
*/
public interface MyOkHttpCall {
//獲取歷史上的今天的資訊
Call getHistoryTodayInfoOnPost(String string);
//獲取天氣介面
Call getWeatherOnGet();
}
2.定義OkHttp工具類
import okhttp3.Call; import okhttp3.OkHttpClient; import okhttp3.Request; import okhttp3.RequestBody; import okhttp3.logging.HttpLoggingInterceptor; import retrodemo.liu.com.retrofitdemo.interface_.MyOkHttpCall; /** * Created by Administrator on 2016/9/27. * 使用單列模式寫OkHttp的網路請求工具類 * 實現介面 */ public class RequestOnOKHttpUtil implements MyOkHttpCall { private final String urlHostory = "http://api.avatardata.cn/GuoNeiNews/Query";//介面(不含引數) private final String urlWeather = "http://api.avatardata.cn/Weather/Query?" + "key=615dcc76298a44329b8db1896852b0cb&cityname=成都";//天氣介面(含引數) private OkHttpClient okHttpClient; private static RequestOnOKHttpUtil requestOnOKHttp = null; public static RequestOnOKHttpUtil getInstance(){ if(requestOnOKHttp == null){ requestOnOKHttp = new RequestOnOKHttpUtil(); } return requestOnOKHttp; } private RequestOnOKHttpUtil(){ HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor(); interceptor.setLevel(HttpLoggingInterceptor.Level.BASIC); //新增攔截器(用於列印請求欄位[包括請求頭,請求體等資訊]) okHttpClient = new OkHttpClient.Builder() .addInterceptor(interceptor) .build(); } /** * OkHttp--Post方式請求資料 * Post請求時需要特別注意請求引數 * @param Parms * @return */ @Override public Call getHistoryTodayInfoOnPost(String Parms) { String requestParms = "key=1dc41caa4c454d48a00e5f970c9fdfcb&page=1&rows=10"; RequestBody requestBody = RequestBody.create(null,requestParms); Request request = new Request.Builder() .url(urlHostory) .post(requestBody) //post方式請求資料,requestBody是請求體 .build(); Call call = okHttpClient.newCall(request); return call; } /** * OkHttp--Get方式獲取天氣資料 * Get請求時url中填入完整的請求地址+請求引數 */ @Override public Call getWeatherOnGet() { Request request = new Request.Builder() .url(urlWeather) .get() //get方式請求資料 .build(); Call call = okHttpClient.newCall(request); return call; } }
OkHttp_Post請求方式的RequestBody獲取方式(老版本)
RequestBody formBody = new FormEncodingBuilder()//老版本獲取ResquestBody的方式
.add("name", "Cuber")
.add("age", "26")
.build();
Request request = new Request.Builder()
.url(url)
.post(RequestBody)
.build();</span>
OkHttp_Post請求方式的RequestBody獲取方式(新版本)
//新版本的請求體獲取方式
FormBody body= new FormBody.Builder()
.add("menu","土豆")
.add("key","08b127d3d67bc05a617fe7aebf1d9670")
.build();
request = new Request.Builder()
.post(body)
.url(baseUrl)
.build();
return client.newCall(request);
3.Callback後臺轉前臺執行
import android.os.Handler;
import android.os.Looper;
import java.io.IOException;
import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.Response;
/**
* Created by Administrator on 2016/9/27.
* Callback的onFailure,onPosnse方法都是在後臺執行緒執行
* 這裡使用Handler將後臺執行轉成Ui主執行緒執行
*/
public abstract class MyOkHttpCallback implements Callback {
//Looper.getMainLooper()表示放到主UI執行緒去處理,不新增表示在當前執行緒處理
private Handler handler = new Handler(Looper.getMainLooper());
@Override
public void onFailure(final Call call, final IOException e) {
handler.post(new Runnable() {
@Override
public void run() {
uiThreadDoOnFailure(call,e);
}
});
}
@Override
public void onResponse(final Call call,final Response response) throws IOException {
handler.post(new Runnable() {
@Override
public void run() {
uiThreadDoOnResponse(call,response);
}
});
}
public abstract void uiThreadDoOnFailure(Call call, IOException e);
public abstract void uiThreadDoOnResponse(Call call, Response response);
}
3.呼叫工具類的方法(activity程式碼)
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.widget.Toast;
import com.google.gson.Gson;
import java.io.IOException;
import java.util.List;
import butterknife.ButterKnife;
import okhttp3.Call;
import okhttp3.Response;
import retrodemo.liu.com.retrofitdemo.interface_.MyOkHttpCallback;
import retrodemo.liu.com.retrofitdemo.requestutil.RequestOnOKHttpUtil;
public class OkHttpActivity extends AppCompatActivity {
private int pages = 1;
private Gson gson = new Gson();
private List<NewsInfo.ShowapiResBodyBean.PagebeanBean.ContentlistBean> list;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_ok_http);
ButterKnife.bind(this);
requestOnPost();
requestOnGet();
}
//天氣資料Okhttp_get
private void requestOnGet() {
Call call = RequestOnOKHttpUtil.getInstance().getWeatherOnGet();
/**
* 非同步載入
* 請求加入排程
* 同步載入方法:call.execute();會丟擲IO異常
*/
call.enqueue(new MyOkHttpCallback() {
@Override
public void uiThreadDoOnFailure(Call call, IOException e) {
Log.e("___測試___Get_OnFailure", "Get_OnFailure");
}
@Override
public void uiThreadDoOnResponse(Call call, Response response) {
try {
Log.e("___測試___Get_onResponce", response.body().string());
} catch (IOException e) {
e.printStackTrace();
}
}
});
}
//歷史上的今天OkHttp-post
private void requestOnPost() {
String parms = "yue=8&ri=28&type=1&page=1&rows=10";
Call call = RequestOnOKHttpUtil.getInstance().getHistoryTodayInfoOnPost(parms);
/**
* 非同步載入
* 請求加入排程
*/
call.enqueue(new MyOkHttpCallback() {
@Override
public void uiThreadDoOnFailure(Call call, IOException e) {
Toast.makeText(OkHttpActivity.this, "uiThreadDoOnFailure_Post", Toast.LENGTH_SHORT).show();
}
@Override
public void uiThreadDoOnResponse(Call call, Response response) {
try {
Log.e("___測試___Post", response.body().string());
} catch (IOException e) {
e.printStackTrace();
}
}
});
}
}
③ 結果演示
2.Retrofit的常規使用【附帶上註解的使用簡介】
① 導包:/新增依賴【程式設計工具Android studio】
compile 'com.squareup.retrofit2:retrofit:2.1.0' compile 'com.squareup.retrofit2:converter-gson:2.1.0'
② 建立請求介面【配置請求引數】
import android.support.annotation.Nullable; import okhttp3.ResponseBody; import retrofit2.Call; import retrofit2.http.GET; import retrofit2.http.Headers; import retrofit2.http.POST; import retrofit2.http.Path; import retrofit2.http.Query; /** * Created by Administrator on 2016/9/28. */ public interface RetrofitCall { //retrofit-getFruit @GET("/cook/query?key=08b127d3d67bc05a617fe7aebf1d9670" + "&menu=土豆&rn=10&pn=3") Call<ResponseBody> getFruit(); //retrofit-postFruit @POST("/cook/query.php") // @Headers("content-type:json") //新增頭資訊固態,放入引數中則變成動態新增 Call<ResponseBody> postFruit(@Query("key") String key , @Query("menu") String menu , @Nullable @Query("rn") String rn , @Nullable @Query("pn") String pn); //okhttp-get okhttp3.Call getFruitOkHttp(); //okhttp-post okhttp3.Call postFruitOkHttp(); } /** * 註解說明(Retrofit請求) * @GET @POST是請求方式 * @Header 新增頭資訊 * * 引數部分使用下列註解 * @Path 表示替換【必填】 * 例: * @GET("book/{id}") * Call<BookResponse> getBook(@Path("id") String id); * @Query 表示可選部分【非必填】程式碼中有用到,這裡就不舉例了 * @QueryMap map<String str> options 表示map形式傳遞可選引數 * 例: * @GET("book/search") * Call<BookSearchResponse> getSearchBooks(@QueryMap Map<String, String> options); * @field表單方式提交 * 例 * @FormUrlEncoded * @POST("book/reviews") * Call<String> addReviews(@Field("book") String bookId, @Field("title") String title, * @Field("content") String content, @Field("rating") String rating); * @FieldMap 與上面類似只是變成了map *例: * @FormUrlEncoded * @POST("book/reviews") * Call<String> addReviews(@FieldMap Map<String, String> fields); * @Body 請求引數有多個,那麼統一封裝到類中應該會更好, * 例; * @FormUrlEncoded * @POST("book/reviews") * Call<String> addReviews(@Body Reviews reviews); * public class Reviews { * public String book; * public String title; * public String content; * public String rating; * } * 還有一個多部分(比較少用) */
③ 建立業務類【處理網路請求】
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.ResponseBody;
import okhttp3.logging.HttpLoggingInterceptor;
import online.liu.com.onlinedemo.inter.RetrofitCall;
import online.liu.com.onlinedemo.obj.User;
import online.liu.com.onlinedemo.obj.UserResult;
import retrofit2.Call;
import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;
import retrofit2.http.Body;
import retrofit2.http.Query;
/**
* Created by Administrator on 2016/9/28.
*/
public class RequestUtil implements RetrofitCall{
private static RequestUtil requestUtil = null;
private OkHttpClient client = null;
private RetrofitCall retrofitCall;
private String Base_postUrl = "http://admin.syfeicuiedu.com";
private String Base_fruitUrl = "http://apis.juhe.cn";
private String Base_fruitUrl_okhttpGet = "http://apis.juhe.cn/cook/query?" +
"key=08b127d3d67bc05a617fe7aebf1d9670" +
"&menu=土豆&rn=10&pn=3";
private String Base_fruitUrl_okhttpPost = "http://apis.juhe.cn/cook/query";
//單例模式
public static RequestUtil getInstance(){
if(requestUtil == null){
requestUtil = new RequestUtil();
}
return requestUtil;
}
//建構函式
private RequestUtil(){
final HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
client = new OkHttpClient.Builder()
.addInterceptor(interceptor) //新增攔截器【Log.d方式列印請求資訊】
.build();
}
//retrofit-Get
@Override
public Call<ResponseBody> getFruitData() {
Retrofit retrofit = new Retrofit.Builder()
.client(client)
.baseUrl(Base_fruitUrl)
//新增Gson轉換器,將返回Json字串轉換成實體類
.addConverterFactory(GsonConverterFactory.create())
.build();
retrofitCall = retrofit.create(RetrofitCall.class);
return retrofitCall.getFruitData();
}
//retrofit-Post-login
@Override
public Call<UserResult> postData(@Body User user) {
Retrofit retrofit = new Retrofit.Builder()
.client(client)
.addConverterFactory(GsonConverterFactory.create())
.baseUrl(Base_postUrl)
.build();
retrofitCall = retrofit.create(RetrofitCall.class);
return retrofitCall.postData(user);
}
//retrofit-Post-fruit
@Override
public Call<ResponseBody> postFruit(@Query("key") String key, @Query("menu") String menu, @Query("rn") int rn, @Query("pn") int pn) {
Retrofit retrofit = new Retrofit.Builder()
.client(client)
.addConverterFactory(GsonConverterFactory.create())
.baseUrl(Base_fruitUrl)
.build();
retrofitCall = retrofit.create(RetrofitCall.class);
return retrofitCall.postFruit(key,menu,rn,pn);
}
//okhttp-get-fruit
@Override
public okhttp3.Call getFruitOkHttp() {
Request request = new Request.Builder()
.url(Base_fruitUrl_okhttpGet)
.get()
.build();
return client.newCall(request);
}
//okhttp-post-fruit
@Override
public okhttp3.Call postFruitOkHttp() {
RequestBody requestBody = RequestBody.create(null,"key=08b127d3d67bc05a617fe7aebf1d9670&menu=土豆&rn=10&pn=3");
Request request = new Request.Builder()
.url(Base_fruitUrl_okhttpPost)
.post(requestBody)
.build();
return client.newCall(request);
}
}
④ Presender類【這裡沒有寫這處理類,直接寫在了Activity中】
mport android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Toast;
import com.google.gson.Gson;
import java.io.IOException;
import java.util.List;
import butterknife.ButterKnife;
import butterknife.OnClick;
import okhttp3.ResponseBody;
import online.liu.com.onlinedemo.R;
import online.liu.com.onlinedemo.conn.RequestUtil;
import online.liu.com.onlinedemo.obj.Friut;
import online.liu.com.onlinedemo.obj.User;
import online.liu.com.onlinedemo.obj.UserResult;
import online.liu.com.onlinedemo.tools.LogTool;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
/**
* Activity類
* 任務:
* 點選按鈕,通過下列的方式去請求網路資料()
* 1.OKHttp_get
* 2.OKHttp_post
* 3.Retrofit_get
* 4.Retrofit_post
*/
public class FruitActivity extends AppCompatActivity {
private Gson gson = new Gson();
private RequestUtil requestUtil;
private List<Friut.ResultBean.DataBean> list;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_fruit);
ButterKnife.bind(this);
requestUtil = RequestUtil.getInstance();
}
private void postFruitOnRetrofit() {
requestUtil.postFruit("08b127d3d67bc05a617fe7aebf1d9670", "土豆", 10, 3).enqueue(new Callback<ResponseBody>() {
@Override
public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
Toast.makeText(FruitActivity.this, "PostFruitOnRetrofit_onResponse應成功", Toast.LENGTH_SHORT).show();
LogTool.e("PostFruitOnRetrofit_onResponse響應成功");
try {
LogTool.e("postFruit_OnRetrofit_onResponse:" + response.body().string());
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public void onFailure(Call<ResponseBody> call, Throwable t) {
LogTool.e("postFruit_OnRetrofit_onFailure");
Toast.makeText(FruitActivity.this, "postFruit_OnRetrofit_onFailure", Toast.LENGTH_SHORT).show();
}
});
}
private void getFruitOnRetrofit() {
requestUtil.getFruitData().enqueue(new Callback<ResponseBody>() {
@Override
public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
Toast.makeText(FruitActivity.this, "getDataOnRetrofit_onResponse", Toast.LENGTH_SHORT).show();
LogTool.e("getDataOnRetrofit_onResponse響應成功");
try {
LogTool.e("getDataOnRetrofit_onResponse:" + response.body().string());
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public void onFailure(Call<ResponseBody> call, Throwable t) {
LogTool.e("getDataOnRetrofit_onFailure");
Toast.makeText(FruitActivity.this, "getDataOnRetrofit_onFailure", Toast.LENGTH_SHORT).show();
}
});
}
//常用於賬號/密碼驗證
private void postDataOnRetrofit() {
requestUtil.postData(new User("zhang", "123")).enqueue(new Callback<UserResult>() {
@Override
public void onResponse(Call<UserResult> call, Response<UserResult> response) {
LogTool.e("響應成功");
UserResult userResult = response.body();
LogTool.e("postDataOnRetrofit_onResponse:" + userResult.getErrmsg());
Toast.makeText(FruitActivity.this, "postDataOnRetrofit_onResponse", Toast.LENGTH_SHORT).show();
}
@Override
public void onFailure(Call<UserResult> call, Throwable t) {
LogTool.e("postDataOnRetrofit_onFailure");
Toast.makeText(FruitActivity.this, "postDataOnRetrofit_onFailure", Toast.LENGTH_SHORT).show();
}
});
}
private void getFruitOnOkHttp() {
requestUtil.getFruitOkHttp().enqueue(new okhttp3.Callback() {
@Override
public void onFailure(okhttp3.Call call, IOException e) {
LogTool.e("getFruitOnOkHttp_onFailure");
}
@Override
public void onResponse(okhttp3.Call call, okhttp3.Response response) throws IOException {
LogTool.e("getFruitOnOkHttp_onResponse" + response.body().string());
}
});
}
private void postFruitOnOkHttp() {
requestUtil.postFruitOkHttp().enqueue(new okhttp3.Callback() {
@Override
public void onFailure(okhttp3.Call call, IOException e) {
LogTool.e("postFruitOnOkHttp_onFailure");
}
@Override
public void onResponse(okhttp3.Call call, okhttp3.Response response) throws IOException {
LogTool.e("postFruitOnOkHttp_onResponse" + response.body().string());
}
});
}
@OnClick({R.id.Okhttp_get, R.id.Okhttp_post, R.id.retrofit_get, R.id.retrofit_post})
public void onClick(View view) {
switch (view.getId()) {
case R.id.Okhttp_get:
getFruitOnOkHttp();
break;
case R.id.Okhttp_post:
postFruitOnOkHttp();
break;
case R.id.retrofit_get:
getFruitOnRetrofit();
break;
case R.id.retrofit_post:
postFruitOnRetrofit();
// postDataOnRetrofit();
break;
}
}
}
⑤ 執行效果