Square 為廣大開發者奉獻了OkHttp,Retrofit1.x,Retrofit2.x,運用比較廣泛,這三個工具有很多相似之處,初學者可能會有一些使用迷惑。這裡來總結一下它們的一些基本使用和一些細微差別。
/************** Retrofit 基本使用方法 Retrofit 到底是返回什麼? void, Observable, Call? *************/ /********************************************Retrofit****************************************************************/ /*** 同步呼叫的方式 ****/ interface GitHubService { @GET("/repos/{owner}/{repo}/contributors") List<Contributor> repoContributors( @Path("owner") String owner, @Path("repo") String repo); } List<Contributor> contributors = gitHubService.repoContributors("square", "retrofit"); /***** 非同步呼叫的方式 僅限於 Retrofit 1.x !!!!!!! *****/ interface GitHubService { @GET("/repos/{owner}/{repo}/contributors") void repoContributors( @Path("owner") String owner, @Path("repo") String repo, Callback<List<Contributor>> cb); // 非同步呼叫新增 CallBack } service.repoContributors("square", "retrofit", new Callback<List<Contributor>>() { @Override void success(List<Contributor> contributors, Response response) { // ... } @Override void failure(RetrofitError error) { // ... } }); /**** Rxjava 方式 ****/ interface GitHubService { @GET("/repos/{owner}/{repo}/contributors") Observable<List<Contributor>> repoContributors( @Path("owner") String owner, @Path("repo") String repo); } // 呼叫 gitHubService.repoContributors("square", "retrofit") .subscribe(new Action1<List<Contributor>>() { @Override public void call(List<Contributor> contributors) { // ... } }); /*******************************注意以下三個Callback的不同***************************************/ // Retrofit Callback Version 1.9 public interface Callback<T> { /** Successful HTTP response. */ void success(T t, Response response); /** * Unsuccessful HTTP response due to network failure, non-2XX status code, or unexpected * exception. */ void failure(RetrofitError error); } // Retrofit Callback Version 2.0 !!!!!!!!! public interface Callback<T> { /** Successful HTTP response. */ void onResponse(Response<T> response, Retrofit retrofit); /** Invoked when a network or unexpected exception occurred during the HTTP request. */ void onFailure(Throwable t); } // OkHttp public interface Callback { void onFailure(Request request, IOException e); void onResponse(Response response) throws IOException; // 注意引數不同 } /*********************************回顧一下Okhttp的呼叫方式********************************************/ //1. 建立 OkHttpClient : OkHttpClient client = new OkHttpClient(); //2. 建立 Request : Request request = new Request.Builder() .url("https://api.github.com/repos/square/okhttp/issues") .header("User-Agent", "OkHttp Headers.java") .addHeader("Accept", "application/json; q=0.5") .addHeader("Accept", "application/vnd.github.v3+json") .build(); //3. 使用 client 執行請求(兩種方式): //第一種,同步執行 Response response = client.newCall(request).execute(); // 第二種,非同步執行方式 client.newCall(request).enqueue(new Callback() { @Override public void onFailure(Request request, Throwable throwable) { // 複寫該方法 } @Override public void onResponse(Response response) throws IOException { // 複寫該方法 } } /***********************************Retrofit 1.0 不能獲得 Header 或者整個 Body*****************************************/ /**********2.x 引入 Call , 每個Call只能呼叫一次,可以使用Clone方法來生成一次呼叫多次,使用Call既可以同步也可以非同步*********/ interface GitHubService { @GET("/repos/{owner}/{repo}/contributors") Call<List<Contributor>> repoContributors( @Path("owner") String owner, @Path("repo") String repo); } Call<List<Contributor>> call = gitHubService.repoContributors("square", "retrofit"); response = call.execute(); /*************** 同步的方式呼叫,注意這裡返回了 Response 後面會提到 ********************/ // This will throw IllegalStateException: 每個Call只能執行一次 response = call.execute(); Call<List<Contributor>> call2 = call.clone(); // 呼叫Clone之後又可以執行 // This will not throw: response = call2.execute(); /************************ 非同步的方式呼叫 *********************************/ Call<List<Contributor>> call = gitHubService.repoContributors("square", "retrofit"); call.enqueue(new Callback<List<Contributor>>() { @Override void onResponse(/* ... */) { // ... } @Override void onFailure(Throwable t) { // ... } }); /****************************引入 Response,獲取返回的RawData,包括:response code, response message, headers**********************************/ class Response<T> { int code(); String message(); Headers headers(); boolean isSuccess(); T body(); ResponseBody errorBody(); com.squareup.okhttp.Response raw(); } interface GitHubService { @GET("/repos/{owner}/{repo}/contributors") Call<List<Contributor>> repoContributors( @Path("owner") String owner, @Path("repo") String repo); } Call<List<Contributor>> call = gitHubService.repoContributors("square", "retrofit"); Response<List<Contributor>> response = call.execute(); /*********************************** Dynamic URL *****************************************/ interface GitHubService { @GET("/repos/{owner}/{repo}/contributors") Call<List<Contributor>> repoContributors( @Path("owner") String owner, @Path("repo") String repo); @GET Call<List<Contributor>> repoContributorsPaginate( @Url String url);// 直接填入 URL 而不是在GET中替換欄位的方式 } /*************************************根據返回值實現過載*****************************************************/ interface SomeService { @GET("/some/proto/endpoint") Call<SomeProtoResponse> someProtoEndpoint(); // SomeProtoResponse @GET("/some/json/endpoint") Call<SomeJsonResponse> someJsonEndpoint(); // SomeJsonResponse } interface GitHubService { @GET("/repos/{owner}/{repo}/contributors") Call<List<Contributor>> repoContributors(..); @GET("/repos/{owner}/{repo}/contributors") Observable<List<Contributor>> repoContributors2(..); @GET("/repos/{owner}/{repo}/contributors") Future<List<Contributor>> repoContributors3(..); // 可以返回 Future } /******************************************Retrofit 1.x Interceptor,新增頭部資訊的時候經常用到Interceptor*************************************************************/ RestAdapter.Builder builder = new RestAdapter.Builder().setRequestInterceptor(new RequestInterceptor() { @Override public void intercept(RequestFacade request) { request.addHeader("Accept", "application/json;versions=1"); } }); /******************************************Retrofit 2.x Interceptor**************************************************/ OkHttpClient client = new OkHttpClient(); client.interceptors().add(new Interceptor() { @Override public Response intercept(Chain chain) throws IOException { Request original = chain.request(); Request request = original.newBuilder() .header("Accept", "application/json") .header("Authorization", "auth-token") .method(original.method(), original.body()) .build(); Response response = chain.proceed(request); return response; } } Retrofit retrofit = Retrofit.Builder() .baseUrl("https://your.api.url/v2/") .client(client).build(); /***************************************非同步例項*********************************************/ public interface APIService { @GET("/users/{user}/repos") Call<List<Repo>> listRepos(@Path("user") String user); @GET("/users/{user}/repos") Call<String> listReposStr(@Path("user") String user); //錯誤,不能這樣使用非同步 // @GET("/users/{user}/repos") // void listRepos(@Path("user") String user, Callback<List<Repo>> callback); } private void prepareServiceAPI() { //For logging HttpLoggingInterceptor logging = new HttpLoggingInterceptor(); logging.setLevel(HttpLoggingInterceptor.Level.BODY); OkHttpClient client = new OkHttpClient(); client.interceptors().add(new MyInterceptor()); client.interceptors().add(logging); // setUp Retrofit Retrofit retrofit = new Retrofit.Builder() .baseUrl("https://api.github.com") //.addConverterFactory(new ToStringConverterFactory()) .addConverterFactory(GsonConverterFactory.create()) .client(client) .build(); service = retrofit.create(APIService.class); } // 非同步呼叫 public void execute() { Call<List<Repo>> call = service.listRepos("pasha656"); call.enqueue(new Callback<List<Repo>>() { @Override public void onResponse(Response<List<Repo>> response, Retrofit retrofit) { if (response.isSuccess()) { if (!response.body().isEmpty()) { StringBuilder sb = new StringBuilder(); for (Repo r : response.body()) { sb.append(r.getId()).append(" ").append(r.getName()).append(" \n"); } activity.setText(sb.toString()); } } else { APIError error = ErrorUtils.parseError(response, retrofit); Log.d("Pasha", "No succsess message "+error.getMessage()); } if (response.errorBody() != null) { try { Log.d("Pasha", "Error "+response.errorBody().string()); } catch (IOException e) { e.printStackTrace(); } } } @Override public void onFailure(Throwable t) { Log.d("Pasha", "onFailure "+t.getMessage()); } }); }