Retrofit框架使用
最近Retrofit使用比較火,並且框架的使用也比較簡單,代碼邏輯看起來也比較清晰。故研究了一下它的使用。
- jar包依賴:okhttp,gson
- 官網定義Retrofit
- 接口定義
public class ApiClient {
private static TestApiInterface mtestService;
public static TestApiInterface getTwitchTvApiClient() {
if (mtestService == null) {
RestAdapter restAdapter = new RestAdapter.Builder()
.setEndpoint("http://ipAddress:8080/AppClient/app")
.build();
mtestService = restAdapter.create(TestApiInterface.class);
}
return mtestService;
}
public interface TestApiInterface {
@POST("/login/getButtonsByUser")
void getStreams(@Query("userView") String limit,
Callback<JustinTvStreamData> callback);
//body形式參數
@POST("/sprint/app/api.htm")
void getStreams(@Body EarningDatas data,
Callback<Response> callback);
}
}
- 使用
ApiClient.getTwitchTvApiClient().getStreams(data, new Callback<Response>() {
/*@Override
public void failure(RetrofitError arg0) {
}
//自動解析成javaBean對象
@Override
public void success(JustinTvStreamData arg0, Response arg1) {
}*/
@Override
public void failure(RetrofitError arg0) {
}
@Override
public void success(Response arg0, Response arg1) {
//自己解析結果
String jsonString = new String(((TypedByteArray) arg0.getBody()).getBytes());
String jsonString1 = new String(((TypedByteArray) arg1.getBody()).getBytes());
//fastjson解析成jsvaBean
JustinTvStreamDatadata=JSON.parseObject(jsonString,JustinTvStreamData.class);
}
});
- 測試數據JavaBean:
public class JavaBean implements Serializable {
public boolean ret ;
public String msg ;
public List<Consignment> consignment;
public class Consignment implements Serializable {
public Double price ;
public String payer ;
public String date ;
public String name ;
public String id ;
public String time ;
public int status ;
}
}
- cache
- 內容來源自鏈接內容正確沒有測試
public class RestClient {
public static final String BASE_URL = "http://something.example.net/JSONService";
private com.ucc.application.rest.ApiService apiService;
public RestClient() {
Gson gson = new GsonBuilder()
.setDateFormat("yyyy'-'MM'-'dd'T'HH':'mm':'ss'.'SSS'Z'")
.create();
RestAdapter restAdapter = new RestAdapter.Builder()
.setLogLevel(RestAdapter.LogLevel.FULL)
.setEndpoint(BASE_URL)
.setClient(new OkClient(OkHttpSingleTonClass.getOkHttpClient()))
.setConverter(new GsonConverter(gson))
.build();
apiService = restAdapter.create(com.ucc.application.rest.ApiService.class);
}
public com.ucc.application.rest.ApiService getApiService() {
return apiService;
}
}
public class OkHttpSingleTonClass {
private static OkHttpClient okHttpClient;
private static final Interceptor REWRITE_CACHE_CONTROL_INTERCEPTOR = new Interceptor() {
@Override
public Response intercept(Chain chain) throws IOException {
Response originalResponse = chain.proceed(chain.request());
return originalResponse.newBuilder()
.header("Cache-Control", String.format("max-age=%d, only-if-cached, max-stale=%d", 120, 0))
.build();
}
};
private OkHttpSingleTonClass() {
}
public static OkHttpClient getOkHttpClient() {
if (okHttpClient == null) {
okHttpClient = new OkHttpClient();
createCacheForOkHTTP();
okHttpClient.networkInterceptors().add(REWRITE_CACHE_CONTROL_INTERCEPTOR);
}
return okHttpClient;
}
private static void createCacheForOkHTTP() {
Cache cache = null;
cache = new Cache(getDirectory(), 1024 * 1024 * 10);
okHttpClient.setCache(cache);
}
public static File getDirectory() {
final File root = new File(Environment.getExternalStorageDirectory() + File.separator + "UCC" + File.separator);
root.mkdirs();
final String fname = UserUtil.CACHE_FILE_NAME;
final File sdImageMainDirectory = new File(root, fname);
return sdImageMainDirectory;
}
}
- https鏈接內容正確沒有驗證
前期使用httpclient與asyncTask進行接口實現, 由於後續httpclient整個被標記爲過期,所以決定採用retrofit或者volley重構接口調用。兩個框架都是比較優秀的,基於我原有項目架構比較適合採用retrofit,所以決定使用retrofit。
具體重構方式我就不具體描述了,和自己寫線程做異步調用區別不大,主要就是client使用了okhttpclient,默認支持gson,我原來就是基於gson做json解析。
另外現在網絡的安全性問題,所以越來越多的服務開始採用https,我的服務端接口也是採用了https接口。但是訪問https接口需要考慮如何導入證書,緩存如何實現。
1、證書部分比較簡單,把導出的證書直接放到, 項目res/raw目錄下,加載證書代碼如下:
InputStream inputStream = null;
inputStream = context.getResources().openRawResource(R.raw.證書名);
CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
Certificate certificate = certificateFactory.generateCertificate(inputStream);
KeyStore keyStore = KeyStore.getInstance("PKCS12", "BC");
keyStore.load(null, null);
keyStore.setCertificateEntry("trust", certificate);
TrustManagerFactory trustManagerFactory = TrustManagerFactory
.getInstance(TrustManagerFactory.getDefaultAlgorithm());
trustManagerFactory.init(keyStore);
SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(null, trustManagerFactory.getTrustManagers(), null);
mOkHttpClient = new OkHttpClient();
mOkHttpClient.setSslSocketFactory(sslContext.getSocketFactory());
mOkHttpClient.setHostnameVerifier(new HostnameVerifier() {
@Override
public boolean verify(String hostname, SSLSession session) {
if (HOST_NAME.equals(hostname))
return true;
return false;
}
});
證書到此就加載到okhttpclient中,然後在adapter中配置client就可以
RestAdapter restAdapter = new RestAdapter.Builder()
.setClient(new OkClient(mOkHttpClient))
.setEndpoint(API_URL).build();
關於緩存查過很多資料,網上提供信息比較有限,最後還是通過自己反覆測試得出的一個結果,也歡迎大牛們提提意見。
首先,需要給okhttpclient設置一個緩存文件
File cacheDir = new File(context.getCacheDir(), RESPONSE_CACHE);
mOkHttpClient.setCache(new Cache(cacheDir, RESPONSE_CACHE_SIZE));
那麼response的緩存如何生效呢,是根據response返回的cache-control確定的,所以這個和服務端的反回結果有關,我將服務端的反回的cache-control設置爲max-age=900,那麼有效期爲15分鐘,當然在發起請求過程中,也是要帶cache-control,其中值可以控制是否訪問緩存,如果需要訪問緩存那麼值就可以設置爲max-age=900, 如果不需要那麼值就設置爲max-age=0即可。具體代碼就是addheader,我就不詳細說了。