1. 程式人生 > >Android網路請求三方庫OkHttp,Retrofit的使用,及其註解使用的簡介

Android網路請求三方庫OkHttp,Retrofit的使用,及其註解使用的簡介

工作內容:

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;
        }
    }
}

⑤  執行效果