Retrofit 2.1 入門

Retrofit 2.1入門 php

 

幾種網絡框架的比較
一、volley
一個簡單的http異步請求庫,但不支持同步,不能post大數據(上傳文件時有問題);
二、android-async-http
和volley同樣,是異步的請求庫,只不過volley使用的是httpUrlConnection,而它使用的是HttpClient。這個庫已經再也不適合Android;
三、okhttp
基於httpUrlConnection,支持同步和異步,但須要本身再封裝下;
四、retrofit;
對 okhttp再次封裝,在項目中能夠直接使用。
在項目中引用retrofit,分爲幾個部分
- module對象
- Converter的實現類
- Service類(定義網址中不固定的部分)
- OkHttpClient和Retrofit java

//1.建立Retrofit對象 android

//2.建立訪問API的請求 git

//3.發送請求 github

//4.處理結果 json

 

一、配置 api

compile 'com.squareup.okhttp3:okhttp-urlconnection:3.4.0-RC1'
compile 'com.google.code.gson:gson:2.7'
compile 'com.squareup.retrofit2:retrofit:2.1.0'
compile 'com.squareup.retrofit2:converter-gson:2.1.0' 服務器

 

GET方式 cookie

public interface SimpleGET {
    @GET("/"//代表是GET方式. "/"會拼接在setEndpoint(url)中url(主機地址)的後面.
    Call<ResponseBody> getResponse();
    //能夠簡單的理解爲網絡訪問完把Response轉換爲一個對象.這裏沒有轉換,仍是Response.
} 網絡

public static void simpleGET(){
    String url="http://tieba.baidu.com";
    Retrofit retrofit=new Retrofit.Builder()
            .baseUrl(url)
            .build();
    SimpleGET create=retrofit.create(SimpleGET.class);
    final  Call<ResponseBody> call=create.getResponse();
    try {
       /*錯誤 的調用
        Response response=create.getResponse().execute();
        System.out.print(response.body().toString());*/
        Response<ResponseBody> bodyResponse = call.execute();
        String body = bodyResponse.body().string();//獲取返回體的字符串
        System.out.print(body);
    } catch (IOException e) {
        e.printStackTrace();
    }
}

POST方式

public interface SimplePOST {
    @POST("/androdi")
    Call<ResponseBody> getResponse();
}

PATH 路徑
path是能夠動態替換的.
static class Contributor {

 //一個pojo類(Plain Ordinary Java Object)簡單的Java對象-->相比javaBean更簡單. GsonConverter默認的轉換器

  String login;

  int contributions;

}  

interface GitHub {

  @GET("/repos/{owner}/{repo}/contributors")

  Call<List<Contributor>> contributors(@Path("owner") String owner, 
@Path("repo") String repo);

} 

 

public static void path_GitHub(){
    String url="https://api.github.com";
    Retrofit retrofit=new Retrofit.Builder()
            .baseUrl(url)
            .addConverterFactory(GsonConverterFactory.create())
            .build();
    GitHub create=retrofit.create(GitHub.class);
    /**
     * 訪問這個地址返回的是一個JsonArray,JsonArray的每個元素都有login
     * 和contributions這2個key和其對應的value.提取出來封裝進POJO對象中.
     */
    Call<List<Contributor>> call=create.contributors("square""retrofit");
    try {
        Response<List<Contributor>> response=call.execute();
        List<Contributor>list=response.body();
        for (Contributor c:list) {
            System.out.println(c.toString());
        }
    } catch (IOException e) {
        e.printStackTrace();
    }
}

 

 

自定義的Converter(StringConverter)
Response能夠得到輸入流,咱們能夠把它轉換成任何想要的格式.

自定義的StringConverter轉換器

public class StringConverter implements Converter<ResponseBody,String>{
    static final StringConverter.Factory FACTORY=new StringConverter.Factory(){
        @Override
        public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[]  annotations, Retrofit retrofit) {
            /*if (type==StringConverter.class)return  new StringConverter();
            else return null;*/
            return  new StringConverter();
        }
    };
    @Override
    public String convert(ResponseBody value) throws IOException {
        //values.string 把服務器上請求的數據,轉換成string格式
//        String str=convertStream2String(value.byteStream());
        return value.string();
    }
    private String convertStream2String(InputStream in) throws IOException {
        //inputStream轉換爲String 要進行gbk或者utf-8轉碼,不然亂碼
        BufferedReader reader = new BufferedReader(new InputStreamReader(in, "GBK"));
//        BufferedReader reader=new BufferedReader(new InputStreamReader(in));
        StringBuilder sb=new StringBuilder();
        String line=null;
        while((line=reader.readLine())!=null){
            sb.append(line);
            sb.append("\n");
            }
        return sb.toString();
    }
}

 

public interface StringClient {
    //方法的返回值是String,須要StringConverter轉換器Converter把Response轉換爲String.
    @GET("/")
    Call<String> getString();
}

public static void Get_String(){
    String url="http://tieba.baidu.com";
    Retrofit retrofit=new Retrofit.Builder()
            .baseUrl(url)
            .addConverterFactory(StringConverter.FACTORY)
            .build();
    final StringClient strClient=retrofit.create(StringClient.class);
    Call<String>call=strClient.getString();
    try {
        Response<String> str=call.execute();
        System.out.print(str.body());
    } catch (IOException e) {
        e.printStackTrace();
    }
}

Query註解
public interface QueryGET {
    @GET("/sheet")
    Call<String> getString(@Query("name") String name,
                           @Query("age")int age,
                           @QueryMap(encoded=true)
                           Map<String, String> filters
                           );
}

public static void QueryGET(){
    String url="http://tieba.baidu.com";
    Map<String, String> map=new HashMap<>();
    map.put("gender","male");
    map.put("address","sz");
    Retrofit retrofit=new Retrofit.Builder()
            .baseUrl(url)
            .addConverterFactory(StringConverter.FACTORY)
            .build();
    QueryGET queryGET=retrofit.create(QueryGET.class);
    Call<String> call=queryGET.getString("laiqurufeng"22, map);
    try {
        Response<String>body=call.execute();
        System.out.print(body.body());
    } catch (IOException e) {
        e.printStackTrace();
    }
}

 

query 訪問的參數會添加到路徑(path)的後面.

實際訪問的url是 http://tieba.baidu.com/sheet?name=laiqurufeng&age=22&gender=male&address=sz  (模擬的訪問)

encoded =true表示對url的query進行url編碼,同理還有encodeValues. 這2個的值默認都是true的

若是上面的代碼換成 map.put("性別","男") ,而後更改@QueryMap(encoded =false ) 

那麼實際訪問的url變成了 http://tieba.baidu.com/sheet?name=laiqurufeng&age=22&性別=%E7%94%B7&address=sz (能夠看到key沒有進行url編碼,value進行了url編碼).

 

Header註解

header分爲key和value都固定,靜態Header註解方法 和 動態Header註解方法

注意header不會相互覆蓋.

靜態Header

interface FixedHeader{

    @Headers({    //靜態Header

        "Accept: application/vnd.github.v3.full+json",

         "User-Agent: Retrofit-Sample-App"

    })

    @GET("/")

                      

    Call<ResponseBody> getResponse();     

}

 

動態Header

interface DynamicHeader{

    @Headers("Cache-Control: max-age=640000")       //態Header

    @GET("/")

Call<ResponseBody> getResponse(

@Header("header1")String header1,

@Header("header2")String header2);

//動態Header,其value值能夠在調用這個方法時動態傳入.

    }

 

 

例子:

 

public class PhoneResult {
    /**
     * errNum : 0
     * retMsg : success
     * retData : {"phone":"15210011578","prefix":"1521001","supplier":"移動","province":"北京","city":"北京","suit":"152卡"}
     */
    public int errNum;
    public String retMsg;
    /**
     * phone : 15210011578
     * prefix : 1521001
     * supplier : 移動
     * province : 北京
     * city : 北京
     * suit : 152卡
     */
    public RetDataEntity retData;
    public static class RetDataEntity {
        public String phone;
        public String prefix;
        public String supplier;
        public String province;
        public String city;
        public String suit;

        @Override
        public String toString() {
            return "RetDataEntity{" +
                    "phone='" phone '\'+
                    ", prefix='" prefix '\'+
                    ", supplier='" supplier '\'+
                    ", province='" province '\'+
                    ", city='" city '\'+
                    ", suit='" suit '\'+
                    '}';
        }
    }
}

Service:

動態Header

public interface PhoneService {
    @GET("/apistore/mobilenumber/mobilenumber")
    Call<PhoneResult> getResult(
            @Header("apikey")String apikey,
            @Query("phone")String phone
    );
}

靜態Header

public interface PhoneServiceDynamic {
    @Headers("apikey:8e13586b86e4b7f3758ba3bd6c9c9135")
    @GET("/apistore/mobilenumber/mobilenumber")
    Call<PhoneResult> getResult(
            @Query("phone")String phone
    );
}

調用

public static void phone_Query(String phone){
    final String BASE_URL="http://apis.baidu.com";
    final String API_KEY="8e13586b86e4b7f3758ba3bd6c9c9135";
    //1.建立Retrofit對象
    Retrofit retrofit=new Retrofit.Builder()
            .baseUrl(BASE_URL)
            .addConverterFactory(GsonConverterFactory.create())
            .build();
    //2.建立訪問API的請求
    PhoneService service=retrofit.create(PhoneService.class);
    Call<PhoneResult>call=service.getResult(API_KEY,phone);
    //3.發送請求
    try {
        Response<PhoneResult>response=call.execute();
        //4.處理結果
        if (response.isSuccessful()) {
            PhoneResult result=response.body();
            if (result!=null) {
                PhoneResult.RetDataEntity entity = result.getRetData();
                System.out.print(entity.toString());
            }
        }
    } catch (IOException e) {
        e.printStackTrace();
    }
    /*異步調用

call.enqueue(new Callback<PhoneResult>() {
        @Override
        public void onResponse(Call<PhoneResult> call, Response<PhoneResult> response) {
            //4.處理結果
            if (response.isSuccessful()) {
                PhoneResult result=response.body();
                if (result!=null) {
                    PhoneResult.RetDataEntity entity = result.getRetData();
                    System.out.print(entity.toString());
                }
            }
        }
        @Override
        public void onFailure(Call<PhoneResult> call, Throwable t) {
        }
    });*/
}

上傳文件

public interface UploadServer {
    @Headers({//靜態Header
            "User-Agent: androidphone"
            })
    @Multipart
    @POST("/service.php?mod=avatar&type=big")
        // upload is a post field
        // without filename it didn't work! I use a constant name because server doesn't save file on original name
        //@Part("filename=\"1\" ") RequestBody
        //以表單的形式上傳圖片
    Call<JsonObject> uploadImageM(@Part("file\";filename=\"1") RequestBody file);
//    Call<ResponseBody> uploadImage(@Part("file\"; filename=\"image.png\"") RequestBody file);
    /**
     * 以二進制流的形式上傳 圖片
     * @param file
     @return
     */
    @Headers({//靜態Header
            "User-Agent:androidphone"
    })
    @POST("/service.php?mod=avatar&type=big")
    Call<ResponseBody> uploadImage(@Body RequestBody file);
}

調用

public static void upload(String fpath) { // path to file like /mnt/sdcard/myfile.txt
    String baseurl="http://dev.123go.net.cn";
    File file = new File(fpath);
    // please check you mime type, i'm uploading only images
    RequestBody requestBody = RequestBody.create(MediaType.parse("image/*"), file);
    /*RequestBody rbody=new MultipartBody.Builder()
            .addPart(requestBody).build();
    RequestBody requestFile =
            RequestBody.create(MediaType.parse("image/jpg"), file);
    MultipartBody.Part body =
            MultipartBody.Part.createFormData("image", file.getName(), requestFile);
    */
    Retrofit retrofit=new Retrofit.Builder()
            .baseUrl(baseurl)
            .addConverterFactory(GsonConverterFactory.create())
            .client(getOkhttpClient())
            .build();
    // 添加描述
    /*String descriptionString = "hello, 這是文件描述";
    RequestBody description =
            RequestBody.create(
                    MediaType.parse("multipart/form-data"), descriptionString);*/
    UploadServer server=retrofit.create(UploadServer.class);
    Call<ResponseBody> call = server.uploadImage(requestBody);
    call.enqueue(new Callback<ResponseBody>() {

        @Override
        public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
            ResponseBody jsonObject=response.body();
            System.out.print(jsonObject.toString());
        }
        @Override
        public void onFailure(Call<ResponseBody> call, Throwable t) {
        }
    });
}

private static OkHttpClient getOkhttpClient(){
        final String cookie="your cookie";
        OkHttpClient httpClient = new OkHttpClient.Builder()
                .addInterceptor(new Interceptor() {
                    @Override
                    public okhttp3.Response intercept(Chain chain) throws IOException {
                        Request request = chain.request()
                                .newBuilder()
//                                .addHeader("Content-Type", " application/x-www-form-urlencoded; charset=UTF-8")
//                                .addHeader("Accept-Encoding", "gzip, deflate")
//                                .addHeader("Connection", "keep-alive")
//                                .addHeader("Accept", "***")
                                .addHeader("Cookie"cookie)
                                .build();
                        return chain.proceed(request);
                    }
                })
                .build();

        return httpClient;
    }



相關文章
相關標籤/搜索