android 多么好用的retrofit

retrofit简介

  1. retrofit来源
    retrofit是大名鼎鼎的Square公司开源的一个优秀的库,用来简化网络请求的,其中的有点不由分说,结合mvp模式使用更是会让你爱不释手。
    什么是mvp模式?点击mvp模式介绍

  2. retrofit优点

    ★ Retrofit使用注解方式,大大简化了我们的URL拼写形式,而且注解含义一目了然,简单易懂。定义网络业务接口Retrofit的网络请求都是写在一个接口中,并使用一定的注释如下面一组请求接口:注意接口中的每个方法的参数都需要使用标注,不采用标注将会报错。

    ```
    /**
     * Created by melo on 2017/3/6.
     * 定义数据接口
     */
    public interface Api {
        @GET(UrlConfig.VIDEO)
        Call<VideoBean> getVideoData();
    
        @POST("{path}?")
        Call<HotBean> getHotData(@Path("path") String path, @QueryMap() Map<String, String> map);
    }
    ```
    

    ★ Retrofit使用简单,结构层次分明,每一步都能清晰的表达出之所以要使用的寓意

    ★ Retrofit支持同步和异步执行,使得请求变得异常简单,只要调用enqueue/execute即可完成

    ★ Retrofit更大自由度的支持我们自定义的业务逻辑,如自定义Converters

    ★ Retrofit简化了网络请求流程,同时自己内部对OkHtttp客户端做了封装,同时2.x把之前1.x版本的部分不恰当职责都转移给OkHttp了(例如Log,目前用OkHttp的Interceptor来实现),这样的好处是职责清晰,Retrofit做自己该做的事儿。

    ★ Retrofit提供不同的Json Converter实现(也可以自定义),同时提供RxJava支持(返回Observable对象),配合Jackson(或者Gson)和RxJava,再加上Dagger2,你的效率至少可以提高一倍。


retrofit请求参数注解类型

  • @Query、@QueryMap
    @GET("type/actor")
    Call<VideoBean> getVideoData(@Query("year") String y);
    //这样做相当于url为 type/actor?year=y
    @POST("{path}?")
    Call<HotBean> getHotData(@Path("path") String path, @QueryMap() Map<String, String> map);
    //假设map 内为 键值对key=a value=A  ,key=b value=B  ,
    //这样做相当于url为path?a =A&b  =B
  • @Field
    //Post方式传递参数,同时在方法上添加@FormUrlEncoded,即以表单的方式传递参数.这里假 设获取注册用户
    @FormUrlEncoded
    @POST("resigeruser/message")
    Call<ResigerUser> getResigerMsg(@Field("type") String allUsers);
  • @Path
    //就是url中的一个替代符号,比如这个api,全是妹子哦http://gank.io/api/data/福利/10/1
    //解释下这个链接 福利对应类型type 10 对应每页返回的条数 1表示页码,就可以表示成
    @GET("{type}/{amount}/{page}")
    Call<List<User>> groupList(@Path("type")  String type , @Path("amount")  String amount , @Path("page")  String page,);
   //如果还时不理解,不妨去试一试,就有体会了
  • @Part
     //用于文件上传,另外需要同时在方法上添加@Multipart,比如注册用户上传的头像
    @Multipart
    @PUT("resigeruser/headportrait ")
    Call<ResigerUser>  submitHeadPortrait (@Part("headportrait ") RequestBody headportrait , @Part("description") RequestBody description);
  • @Header 和@Headers 就是单个头部和多个头部的意思,下面会有使用到。

retrofit使用

▲get请求

  1. 第一步在module中配置bulid.gradle
dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    testCompile 'junit:junit:4.12'
    compile 'com.android.support:appcompat-v7:25.3.1'
    //okhttp+retrofit
    compile 'com.squareup.okhttp3:okhttp:3.5.0'
    compile 'com.squareup.retrofit2:retrofit:2.0.2'
    //gson
    compile 'com.squareup.retrofit2:converter-gson:2.0.2'
}

添加依赖okhttp包和retrofit包,另外需要添加converter-gson包,retrofit的优点中已经介绍过这点,所以这个是不可缺少的。
2. 第二步定义retrofit访问的Api接口类

/**
 * Created by melo on 2017/3/6.
 * 定义数据接口
 */
public interface Api {
     @GET(UrlConfig.SHEHUI)
       Call<ShehuiBean> getString();
}

可以清楚的看到上面的注解@GET就是用get请求的方式,返回的是一个ShehuiBean类型的结果
3. 第三步编写RetrofitHelper类

/**
 * Created by melo on 2017/3/6.
 * 定义retrofit类
 */
public class RetrofitHelper {
    private static volatile RetrofitHelper instance = null;

    private RetrofitHelper() {

    }
    //创建单例
    public static RetrofitHelper getInstance() {
        if (instance == null) {
            synchronized (RetrofitHelper.class) {
                if (instance == null) {
                    instance = new RetrofitHelper();
                }
            }
        }
        return instance;
    }

    //创建OkHttpClient 对象
    public OkHttpClient createHttpClient() {
        OkHttpClient client = new OkHttpClient.Builder()
                .connectTimeout(60 * 1000, TimeUnit.MILLISECONDS)
                .readTimeout(60 * 1000, TimeUnit.MILLISECONDS)
                .build();
        return client;
    }
//创建Retrofit 对象
    public Retrofit createRetrofit() {
        return new Retrofit.Builder()
                .baseUrl(UrlConfig.BASE_URL)
                .client(createHttpClient())
                //gson解析要加
                .addConverterFactory(GsonConverterFactory.create(createGson()))
                //rxjava 需要添加
                //.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
                .build();
    }
//创建Api 对象
    public Api getService() {
        Retrofit retrofit = createRetrofit();
        Api apiService = retrofit.create(Api.class);
        return apiService;
    }

    /**
     * @return
     */
    public Gson createGson() {
        return new GsonBuilder()
                .serializeNulls()
                .enableComplexMapKeySerialization()
//                .setDateFormat("")
                .create();
    }
}

这个类中的方法就不用多说了
4. 最后再看我们的MainActivity代码也不多

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        RetrofitHelper.getInstance().getService().getString().enqueue(new Callback<ShehuiBean>() {
            @Override
            public void onResponse(Call<ShehuiBean> call, Response<ShehuiBean> response) {
                if (response.isSuccessful()){
                    ShehuiBean shehuiBean= response.body();
                    Log.i("tag",shehuiBean.getTitle());
                }
            }

            @Override
            public void onFailure(Call<ShehuiBean> call, Throwable t) {
                Log.i("tag","下载失败");
            }
        });
    }
}

这里用了enqueue异步请求,以为耗时操作基本都是异步调度的嘛

这是基本的get请求


▲ post请求
post请求 和get在请求方式上的不同之处在于post将各种参数都放在包体中,这样做自然就是比较安全,不至于想get方式一样请求参数都暴露在外部

接下来看我们如何操作的呢

  1. 第一步,在Api接口类中增加post请求方法
/**
 * Created by melo on 2017/3/6.
 * 定义数据接口
 */
public interface Api {
    @GET(UrlConfig.SHEHUI)
    Call<ShehuiBean> getString();

    @POST("{path}?")
    Call<GuoNeiBean> getGuoNeiData(@Path("path") String path, @QueryMap() Map<String, String> map);
}

对于请求体不确定的参数赢{}?的方式,比如如下链接http://v.juhe.cn/toutiao/index?type=guonei&key=723060051cc0b5baa348a8024b1bb7e1
此处的index页码是不确定的,就可以用上述方式改造。
2. 第二步直接就可以去请求网络了,先看代码

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        //社会  get请求
        RetrofitHelper.getInstance().getService().getString().enqueue(new Callback<ShehuiBean>() {
            @Override
            public void onResponse(Call<ShehuiBean> call, Response<ShehuiBean> response) {
                if (response.isSuccessful()){
                    ShehuiBean shehuiBean = response.body();
                    Log.i("tag", "社会:" +shehuiBean.getResult().getData().get(0).getTitle());
                }
            }

            @Override
            public void onFailure(Call<ShehuiBean> call, Throwable t) {
                Log.i("tag","下载失败");
            }
        });


        //国内 post请求
        HashMap<String, String> map = new HashMap<>();
        map.put("type", "guonei");
        map.put("key", "723060051cc0b5baa348a8024b1bb7e1");
        RetrofitHelper.getInstance().getService().getGuoNeiData(UrlConfig.GUONEI,map).enqueue(new Callback<GuoNeiBean>() {
            @Override
            public void onResponse(Call<GuoNeiBean> call, Response<GuoNeiBean> response) {
                if (response.isSuccessful()) {
                    GuoNeiBean guoNeiBean = response.body();
                    Log.i("tag", "国内:" + guoNeiBean.getResult().getData().get(0).getTitle());
                }
            }

            @Override
            public void onFailure(Call<GuoNeiBean> call, Throwable t) {

            }
        });
    }
}

可以看到我们用map将所请求的参数以键值对的形式装了起来,还可以通过传入页面index去控制所要下载的数据

▲ 上传图片
这里先留着吧,因为我自己没有搭建本地的服务,后面有机会在补充
想了解这部分点击此处

拦截器???

以上两种请求都是基本的用法,但是一般项目中post请求除了键值对,也还会遇到json、xml的请求,后台也做了约束,约束其上传格式为json/xml,防止乱入,一般会需要添加头文件headers

方式一:在Api接口类的方法中注解添加

public interface Api {
    @GET(UrlConfig.SHEHUI)
    Call<ShehuiBean> getString();

    @Headers({"Content-Length:200","Content-type:application/json",})//分别为 请求内容长度限制,请求限制为json格式
    @POST("{path}?")
    Call<GuoNeiBean> getGuoNeiData(@Path("path") String path, @QueryMap() Map<String, String> map);
}

上述添加的请求头不一定在此处合适,但是用法雷同。

方式二:添加拦截器,在拦截器内添加header,便于统一管理

/**
 * Created by melo on 2017/8/9.
 * header拦截器
 */
public class NetInterceptor implements Interceptor{
    @Override
    public Response intercept(Chain chain) throws IOException {
        Request.Builder builder = chain.request().newBuilder();
        Request requst = builder.addHeader("Content-type", "application/json")
                .addHeader("Content-Length","300")
                .build();
        return chain.proceed(requst);
    }
}

至于需要增加什么样的限制,继续addHeader就可以。

接下来就需要修改RetrofitHelper中Httpclient的构建

 public OkHttpClient createHttpClient() {
        OkHttpClient client = new OkHttpClient.Builder()
                .connectTimeout(60 * 1000, TimeUnit.MILLISECONDS)
                .readTimeout(60 * 1000, TimeUnit.MILLISECONDS)
                //添加拦截器
                .addInterceptor(new NetInterceptor())
                .build();
        return client;
    }

然后去掉Api中刚才方式一添加的Headers就可以了,Api方法中就可以用Body体去传json类型的bean类了(此处不能直接在方法内传string类型的字符串哦,需自行体会)

github:demo链接

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值