美文网首页
Retrofit的简单用法

Retrofit的简单用法

作者: 上官若枫 | 来源:发表于2017-09-22 17:27 被阅读15次

    最近在啃retrofit和Rx_Java,以现在的水平只能说是略懂皮毛,只会简单使用,但是尽管懂得少,我也要继续写下去,我相信一直坚持下去总会有收获。

    1.Retrofit的使用
    先来说一下大概的需求,就是输入百度网址,拿到返回的body
    首先需要给项目定义一个接口,用于后边的发送请求。

    public interface Service {
        @GET("/")//用来写子目录
        Call<String> getBaidu();
    }
    

    这里我们先采用get方法发送网络请求,@GET为retrofit的注解,后边的注释是用于写子目录的。如何理解这个呢,你想要在百度上搜索“图片”两个关键字,点击enter键,会出现搜索结果,这时候浏览器上的IP地址已经变成了“https://www.baidu.com/xxxxxxx”在这里retrofit将网址url分成两部分“www.baidu.com”作为baseURL,斜杠后面的作为子目录。
    再来看一下 getBaidu()方法,由于这里声明的是接口,所以没有方法体,但是其返回类型是retrofit里的Call类型,泛型为拿到String,这里泛型可以自己改,根据你拿到网络数据以后,想要对他做如何的处理,现在的需求只是拿到返回体
    接下来开始使用retrofit对象生成实体,并访问网络,代码如下:

     Retrofit retrofit = new Retrofit.Builder()
                    .baseUrl("http://www.baidu.com")
                    .addConverterFactory(
                            new Converter.Factory() {
                                @Nullable
                                @Override
                                public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations, Retrofit retrofit) {
                                    return new Converter<ResponseBody, String>() {
                                        @Override
                                        public String convert(ResponseBody value) throws IOException {
                                            return value.string();
                                        }
                                    };
                                }
                            }
                    ).build();
    

    从上面代码可以看出,Retrofit是通过build方式来创建对象的。咱们一行一行的来看代码baseURL方法是为retrofit添加基本网址,前面已经介绍过了。
    由于我们访问网络以后拿到的数据可能多样,可能是二进制流或者网络请求回调,在这里我们利用addConverterFactory方法对拿到的返回体进行转化,在后边实战过程中这段代码不需要我们自己写。这次我们将返回体的内容转化为string
    build方法建立实体对象。
    接下来利用retrofit的Call将任务分发出去并执行。代码如下

     Service service = retrofit.create(Service.class);//通过接口代理,创建service实例
            Call<String> call = service.getBaidu();
            call.enqueue(this);
    

    后边将activity实现Callback<String>接口,并复写两个方法

    @Override
        public void onResponse(Call<String> call, Response<String> response) {
            tv.setText(response.body());
        }
    
        @Override
        public void onFailure(Call<String> call, Throwable t) {
    
        }
    

    在onResponse方法里可以将拿到的string对象显示在UI上面。
    Activity的整体代码如下:

    import android.os.Bundle;
    import android.support.annotation.Nullable;
    import android.support.v7.app.AppCompatActivity;
    import android.widget.TextView;
    
    import java.io.IOException;
    import java.lang.annotation.Annotation;
    import java.lang.reflect.Type;
    
    import okhttp3.ResponseBody;
    import retrofit2.Call;
    import retrofit2.Callback;
    import retrofit2.Converter;
    import retrofit2.Response;
    import retrofit2.Retrofit;
    
    public class MainActivity extends AppCompatActivity implements Callback<String> {
        TextView tv;
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            tv = (TextView) findViewById(R.id.tv);
            Retrofit retrofit = new Retrofit.Builder()
                    .baseUrl("http://www.baidu.com")
                    .addConverterFactory(
                            new Converter.Factory() {
                                @Nullable
                                @Override
                                public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations, Retrofit retrofit) {
                                    return new Converter<ResponseBody, String>() {
                                        @Override
                                        public String convert(ResponseBody value) throws IOException {
                                            return value.string();
                                        }
                                    };
                                }
                            }
                    ).build();
            Service service = retrofit.create(Service.class);//通过接口代理,创建service实例
            Call<String> call = service.getBaidu();
            call.enqueue(this);
    
        }
    
        @Override
        public void onResponse(Call<String> call, Response<String> response) {
            tv.setText(response.body());
        }
    
        @Override
        public void onFailure(Call<String> call, Throwable t) {
    
        }
    }
    

    xml文件很简单就一个textview,这里就不再写
    2.用retrofit来解析json数据
    这里用的是视频教程里的API接口,但是API有点久远无法使用,代码是没问题的。简单来说一下吧。
    首先是Service接口

    public interface Service {
        /*
        * get请求
        * */
    //    @GET("/api/{category}/list")
    //    Call<Tngou> getList(@Path("category")String category,@Query("id") int id, @Query("page") int page, @Query("rows")int rows);//请求参数写在括号里
        /*
        * post请求
        * */
        @POST("/api/{category}/list")
        Call<Tngou> getList(@Path("category")String category, @Field("id") int id, @Field("page") int page, @Field("rows") int rows);//请求参数写在括号里
    
    

    链接为变化的,假如对于一个api连接而言有很多种类,有食谱,新闻,微信头条文章,他们对应的API子目录可能是“/api/cook/list”,“/api/news/list”,“/api/weixin/list”大家可以看到这三个API对应的连接就中间的发生了变化,其他的没有变。这时候retrofit为解决代码复用问题添加了@path注解可以动态变换ip。另外还有请求参数,用@Query来注解。
    下面的是post请求,就是注解需要换一下,其他的都一样,不再解释。
    在这里需要注意的是返回类型 Call<Tngou>,泛型为Tngou,这个泛型是自己定义的,相当于gson对应的Javabean。

    import com.google.gson.annotations.SerializedName;
    
    import java.util.List;
    
    /**
     * Created by 上官若枫 on 2017/9/19.
     */
    
    public class Tngou {
        //使用注解让类的属性命名更加友好
        @SerializedName("status")
        private boolean status;
        @SerializedName("total")
        private int total;
        @SerializedName("tngou")
        private List<Cook>list;
    
        public boolean isStatus() {
            return status;
        }
    
        public void setStatus(boolean status) {
            this.status = status;
        }
    
        public int getTotal() {
            return total;
        }
    
        public void setTotal(int total) {
            this.total = total;
        }
    
        public List<Cook> getList() {
            return list;
        }
    
        public void setList(List<Cook> list) {
            this.list = list;
        }
    }
    

    javabean 里面有一个@SerializedName注解,这个呢会让属性命名更加友好,啥意思??假如json数据流里面写的是属性是“n”代表name,那你在写对应的Javabean里面写n就不合适了,加上这个注解,你的命名可以随便写。
    下面是activity的代码

    public class MainActivity extends AppCompatActivity implements Callback<Tngou> {
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            Retrofit retrofit = new Retrofit.Builder()
                    .baseUrl("http://www.tngou.net")
                    .addConverterFactory(GsonConverterFactory.create())
                    .build();
            Service service = retrofit.create(Service.class);
            Call<Tngou> call = service.getList("cook",0,1,20);
            call.enqueue(this);
        }
    
        @Override
        public void onResponse(Call<Tngou> call, Response<Tngou> response) {
            List<Cook> list = response.body().getList();
        }
    
        @Override
        public void onFailure(Call<Tngou> call, Throwable t) {
    
        }
    }
    

    这里面的addConverterFactory方法里不需要我们自己写了,直接用retrofit的gson解析,利用retrofit.create(Service.class);创造实体类,然后调用.getList方法将参数输入进去。在 onResponse方法里面拿到结果并进行处理。
    感兴趣的同学可以关注一下我的微信公众号,或者微信搜索 开发 Android的小学生

    qrcode_for_gh_c686d73be7e1_430.jpg

    相关文章

      网友评论

          本文标题:Retrofit的简单用法

          本文链接:https://www.haomeiwen.com/subject/usefextx.html