你的位置:首页 > 操作系统

[操作系统]retrofit2 使用教程 及 Android 网络架构搭建 (原创)


squareup 推出 retrofit2 已经有一段时间了,现在的版本比较稳定,没有什么大坑了。网络上的教程要么太简单,只是个Demo;要么有些落时,要么复用性比较差,所以自己写个教程(alex9xu@hotmail.com),供大家参考。

 

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 Alex9Xu@hotmail.com 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 Alex9Xu@hotmail.com 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 Alex9Xu@hotmail.com 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 Alex9Xu@hotmail.com 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 Alex9Xu@hotmail.com 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 ,注意,其中两项是公共参数。

 

好了,这样就可以正常运行了。