squareup 推出 retrofit2 已經有一段時間了,現在的版本比較穩定,沒有什麼大坑了。網路上的教程要麼太簡單,只是個Demo;要麼有些落時,要麼復用性比較差,所以自己寫個教程([email protected]),供大家參考。 1. 首先在build.gradle引入依賴 註意,這裡 ...
squareup 推出 retrofit2 已經有一段時間了,現在的版本比較穩定,沒有什麼大坑了。網路上的教程要麼太簡單,只是個Demo;要麼有些落時,要麼復用性比較差,所以自己寫個教程([email protected]),供大家參考。
1. 首先在build.gradle引入依賴
compile 'com.squareup.retrofit2:retrofit:2.1.0'
compile 'com.squareup.retrofit2:converter-gson:2.1.0'
compile 'com.squareup.okhttp3:logging-interceptor:3.3.1'
註意,這裡的 logging 用於輸出網路交互的Log,對於開發調試極其有用。之前retrofit2因為不能輸出Log被人嫌棄了很久,各高手實現了幾種列印Log的方式,現在總算有官方的了。
2. 這是工具類
import okhttp3.HttpUrl;
import okhttp3.Interceptor;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import okhttp3.logging.HttpLoggingInterceptor;
import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory; import com.alex9xu.test.config.AppConfigInterface; import java.io.IOException;
/** * Created by [email protected] on 2016/7/13 */public class RetrofitBase { private static Retrofit mRetrofit; public static Retrofit retrofit() { if (mRetrofit == null) { OkHttpClient client; // Notice: The only differ of debug is: HttpLoggingInterceptor
if(!AppConfigInterface.isDebug) { client = new OkHttpClient.Builder() .addInterceptor(new Interceptor() { @Override
public Response intercept(Chain chain) throws IOException { Request original = chain.request();
HttpUrl originalHttpUrl = original.url();
HttpUrl url = originalHttpUrl.newBuilder() .addQueryParameter("Id", "123456") .addQueryParameter("deviceType", "0") .build();
// Request customization: add request headers
Request.Builder requestBuilder = original.newBuilder() .url(url);
Request request = requestBuilder.build();
return chain.proceed(request); } }) .build();
} else { HttpLoggingInterceptor logging = new HttpLoggingInterceptor();
logging.setLevel(HttpLoggingInterceptor.Level.BODY);
client = new OkHttpClient.Builder() .addInterceptor(logging) .addInterceptor(new Interceptor() { @Override
public Response intercept(Chain chain) throws IOException { Request original = chain.request();
HttpUrl originalHttpUrl = original.url();
HttpUrl url = originalHttpUrl.newBuilder() .addQueryParameter("Id", "123456") .addQueryParameter("deviceType", "0") .build();
// Request customization: add request headers
Request.Builder requestBuilder = original.newBuilder() .url(url);
Request request = requestBuilder.build();
return chain.proceed(request); } }) .build();
} mRetrofit = new Retrofit.Builder() .baseUrl(AppConfigInterface.BASE_COM_URL) .addConverterFactory(GsonConverterFactory.create()) .client(client) .build(); } return mRetrofit; } }
講解一下:
(1) 通過 addInterceptor 實現的列印日誌及加入多個公共參數功能。
(2) 除了含有 HttpLoggingInterceptor 外,測試的和正式的,沒有任何區別。通過全局變數控制是否為正式環境,如果是正式環境則不輸出網路交互相關的Log。
(3) 可以通過 addQueryParameter("deviceType", "0") 的形式加入多個公共參數,這樣所有的請求都會帶該參數。
(4) 這裡 BASE_COM_URL 是 http://test.hello.com/ 的形式。
3. 使用方式:
(1) 先寫介面
import android.support.v4.util.ArrayMap; import com.alex9xu.test.config.AppConfigInterface; import com.alex9xu.test.model.ClassifyListResult; import retrofit2.Call;
import retrofit2.http.GET;
import retrofit2.http.QueryMap; /** * Created by [email protected] on 2016/7/14 */
public interface ClassifyApi { @GET(AppConfigInterface.CLASSIFYLIST) Call<ClassifyListResult> getClassify(@QueryMap ArrayMap<String,String> paramMap);}
這裡通過Post提交參數,參數存儲在Map里,可以添加多組參數。註意,我使用了ArrayMap,這是Android里特有的一種形式,記憶體占用只有HashMap的十分之一左右。
String CLASSIFYLIST = "query/classify.html";
(2) 再寫返回值結構
import com.alex9xu.test.base.BaseResponse; import com.alex9xu.test.model.entity.ClassfiyBean; import java.util.List; /** * Created by [email protected] on 2016/7/14 */public class ClassifyListResult extends BaseResponse { private DataEntity data; public DataEntity getData() { return data; } public static class DataEntity { private List<ClassfiyBean> classifyList; public List<ClassfiyBean> getClassifyList() { return classifyList; } } }
/** * Created by [email protected] on 2016/7/14 */public class ClassfiyBean { private String icon; private String name; public String getIcon() { return icon; } public String getName() { return name; } }
返回的數據寫成如上形式,以利於復用。
(3) 調用
import com.alex9xu.test.model.ClassifyListResult; import com.alex9xu.test.model.entity.ClassfiyBean; import com.alex9xu.test.net.ClassifyApi; import com.alex9xu.test.net.RetrofitBase;
/** * Created by [email protected] on 2016/7/14 */
public class MainActivity extends AppCompatActivity{
...
private void getData() { ArrayMap<String,String> paramMap = new ArrayMap<>();
paramMap.put("version", "1.0");
paramMap.put("uid", "654321");
ClassifyApi classifyApi = RetrofitBase.retrofit().create(ClassifyApi.class);
Call<ClassifyListResult> call = classifyApi.getClassify(paramMap);
call.enqueue(new Callback<ClassifyListResult>() { @Override
public void onResponse(Call<ClassifyListResult> call, Response<ClassifyListResult> response) { LogHelper.d(TAG, "getClassify, Suc");
LogHelper.d(TAG, "getClassify = " + response.body());
if(null != response.body() && null != response.body().getData()) { List<ClassfiyBean> list = response.body().getData().getClassifyList();
if(null != list && list.size()>0) { mTvwDisplay.setText(list.get(0).getName());
} } } @Override
public void onFailure(Call<ClassifyListResult> call, Throwable t) { LogHelper.e(TAG, "getClassify, Fail");
} });
}
...
講解:會拼接成 https://test.hello.com/query/classify.html?uid=654321&version=1.0&Id=123456&deviceType=0 ,註意,其中兩項是公共參數。
好了,這樣就可以正常運行了。