Retrofit2.0使用

来源:互联网 发布:淘宝魔镜插件免费版 编辑:程序博客网 时间:2024/05/21 09:36

        前几天学习了Retrofit相关知识,网络请求这块一般很抵触去学,但是又像是一个宝箱诱惑着你去探索尝试,于是,看了官方两篇基础教程,先简单实现一下访问豆瓣或者知乎网站的数据,并将其用Listview或者RecyclerView显示出来。先放上最后的效果图:


话不多说,让我们边学边做。

一. Retrofit概述:

1.Retrofit是什么?

Retrofit是Square公司开发的一款针对Android网络请求的框架,Retrofit2底层基于OkHttp实现的,OkHttp现在已经得到Google官方认可,大量的app都采用OkHttp做网络请求,其源码详见OkHttp Github官方描述是这样的:A type-safe REST client for Android and Java.

对于Java和Android来讲,它是一款安全的REST客户端。从定义来讲可能比较晦涩难懂,最好的方式就是通过实战来挖掘它的用法。

2.Retrofit用来干嘛?

用注解去描述HTTP请求,同时Retrofit默认集成URL参数替换和查询参数.除此之外它还支持 Multipart请求和文件上传。开发一个自己的用于请求 REST API 的类型安全的网络请求库是一件很痛苦的事情:你需要处理很多功能,比如建立连接,处理缓存,重连接失败请求,线程,响应数据的解析,错误处理等等。从另一方面来说,Retrofit 是一个有优秀的计划,文档和测试并且经过考验的库,它会帮你节省你的宝贵时间以及不让你那么头痛。


二. Retrofit的用法:

1.首先,需要通过build.grade来添加依赖:
在你的项目中设置 Retrofit依赖。 根据你自己的构建工具,在pom.xml或者build.gradle中定义Retrofit和它的依赖关系。当运行命令去构建你的项目时,构建系统会在你的项目里下载相应的库。 我们建议用OkHttp搭配Retrofit,OKHttp同样需要定义Okio依赖。
dependencies {
// Retrofit & OkHttp
compile 'com.squareup.retrofit2:retrofit:2.1.0'
compile 'com.squareup.retrofit2:converter-gson:2.1.0'

}

2.添加网络权限:
我们需要使用Retrofit实现网络请求数据,所以,这里权限是必须的
<uses-permission android:name="android.permission.INTERNET" />

3.我们需要拿来目标网址:
网络请求一定会有个目标数据的源头,一般为http/https格式,这里我们使用的是知乎的新闻api作为测试网址:
http://news-at.zhihu.com/api/4/news/latest
这里我们请求的是最新的新闻,我们可以将网址放在浏览器中搜一下,发现里面都是json类型的数据,对,这就是我们需要的,接下来我们就需要对json数据进行解析了,
一般常用的就是Gson解析工具了,那我们就用Gson来进行解析操作,可以看到我们build.grade中有个com.squareup.retrofit2:converter-gson:2.1.0' 此
Gson是retrofit内集成的json转换器,我们如果要对Json数据进行解析,还需要另外导入官方gson框架。

4.必不可少的两个工具:
如果你想要获取到网址内的json数据,那么Postman将会是一个强力帮手,将网址放入输入栏后,点击 Enter —— 它将会根据那个地址执行一个 GET 请求,你会看到返回
的是一个 JSON 对象数组,下面的截图是使用了 Postman 的 JSON 响应结果:


得到了我们的json数据,接下来就需要将其转换为我们的Java对象类型了,这就需要我们的第二个工具:jsonschema2pojo,和强大的生成器,网址:
http://www.jsonschema2pojo.org/
我们将postman上得到的json数据复制粘贴到jsonschema的输入栏,设定如下:


将source type设为Json,annotation style设为Gson,取消Allow additional properties的选定,然后我们点击下面的priview即可:



如图,这样我们就得到三个java类,都不需要我们自己封装实现,是不是很方便。下面我们将三个类复制到自己创建的工程中就可以了:

生成的三个实体类:NewsInfo,Stroy,TopStory,其中NewsInfo类中包含Stroy和TopStory的对象,数据比较多,这里就不放上实体类了。
下面开始retrofit的编写吧。

5.为Retrofit创建api工具类:
既然知道了数据的格式以及数据的来源,那我们得写个类定义baseUri让Retrofit可以访问呀:
package com.app.ui;/** * Created by MuFeng on 2017/4/18. * 应用网络请求的工具类 */public class ApiUtils {    public static final String BASE_URL = "http://news-at.zhihu.com/api/4/";}

6.为Retrofit创建API接口:
这个自定义WebRequestService接口包含了我们将会用到用于执行网络请求的方法,比如 GETPOSTPUTPATCH, 以及 DELETE。在这里,我们将执行一个 GET 请求。
更多请求可以参考这篇文章:http://wuxiaolong.me/2016/06/18/retrofits/
/** * Created by MuFeng on 2017/4/18. * 创建网络请求的接口 */public interface WebRequestService {    @GET("news/latest")    Call<NewsInfo> getRequest();//从服务器端过滤数据,获取传入变量对应的数据}

7.接下来,我们就用Recyclerview让数据显示出来了:
因为数据还是挺多的,所以用recyclerview以列表方式显示会看起来清晰美观一点,这里只放上Recyclerview的adapter代码,布局就省略了:
/** * Created by MuFeng on 2017/4/18. * 适配 */public class NewsAdapter extends RecyclerView.Adapter<NewsAdapter.ViewHolder>{    private Context context;    List<String> titleData;    List<String> bmpData;    private MyItemListener myItemListener;//item的点击监听器    public NewsAdapter(Context context, List<String> titleData, List<String> bmpData){        this.titleData=titleData;        this.bmpData=bmpData;        this.context=context;    }    @Override    public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {        LayoutInflater layoutInflater=LayoutInflater.from(context);        View view=layoutInflater.inflate(R.layout.item_news,parent,false);        ViewHolder myViewHolder=new ViewHolder(view);        return myViewHolder;    }    @Override    public void onBindViewHolder(ViewHolder holder, int position) {        TextView textView=holder.textView;        ImageView imageView=holder.imageView;        textView.setText(titleData.get(position));        Glide.with(context).load(bmpData.get(position)).into(imageView);//加载图片    }    @Override    public int getItemCount() {        return titleData.size();    }    public class ViewHolder extends RecyclerView.ViewHolder{        ImageView imageView;        TextView textView;        public ViewHolder(View itemView) {            super(itemView);            imageView= (ImageView) itemView.findViewById(R.id.item_img);            textView= (TextView) itemView.findViewById(R.id.item_text);        }    }    //item的监听器接口    public interface MyItemListener{        void onClickMyItem(View view,int position);    }    //设置监听    public void setMyItemListener(MyItemListener myItemListener){        this.myItemListener=myItemListener;    }}

附上item的布局吧:
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:app="http://schemas.android.com/apk/res-auto"    android:orientation="horizontal"    android:layout_width="match_parent"    android:layout_height="wrap_content">    <android.support.v7.widget.CardView        android:layout_width="match_parent"        android:layout_height="wrap_content"        app:cardCornerRadius="5dp"        android:layout_marginBottom="10dp"        android:layout_marginLeft="8dp"        android:layout_marginRight="8dp">        <LinearLayout            android:layout_width="match_parent"            android:layout_height="wrap_content"            android:orientation="horizontal"            android:gravity="center_vertical">            <ImageView                android:id="@+id/item_img"                android:layout_width="100dp"                android:layout_height="100dp"                android:layout_margin="5dp"/>            <TextView                android:id="@+id/item_text"                android:layout_width="wrap_content"                android:layout_height="wrap_content"                android:textSize="18sp"                android:layout_marginLeft="8dp"/>        </LinearLayout>    </android.support.v7.widget.CardView></LinearLayout>
这里我们只需要显示的内容是新闻的title以及图片。

8.使用Retrofit执行网络请求:
需要先创建retrofit的实例,再为其制定baseUrl以及gson转换器,然后新建WebRequestService实例,通过call对象调用enqueue()方法进行网络请求,

enqueue() 会发送一个异步请求,当响应结果返回的时候通过回调通知应用。因为是异步请求,所以 Retrofit 将在后台线程处理,这样就不会让 UI 主线程堵塞或者受到影响。

要使用 enqueue(),你必须实现这两个回调方法:

  • onResponse()
  • onFailure()

只有在请求有响应结果的时候才会调用其中一个方法。

  • onResponse():接收到 HTTP 响应时调用。该方法会在响应结果能够被正确地处理的时候调用,即使服务器返回了一个
  • 错误信息。所以如果你收到了一个 404 或者 500 的状态码,这个方法还是会调用。为了拿到状态码以便后续的处理,你可以
  • 使用 response.code() 方法。你也可以使用 isSuccessful() 来确定返回的状态码是否在 200-300 范围内,该范围的
  • 状态码也表示响应成功。
  • onFailure():在与服务器通信的时候发生网络异常或者在处理请求或响应的时候发生异常的时候调用。

如果要执行同步请求,你可以使用 execute() 方法。要注意同步请求在主线程会阻塞用户的任何操作。所以不要在主线程执行同步请求,要在后台线程执行。

下面附上实现代码:


//进行网络请求,获取首页数据private void fillNewsContent() {    Retrofit retrofit = new Retrofit.Builder()            .baseUrl(ApiUtils.BASE_URL)            .addConverterFactory(GsonConverterFactory.create())//使用Gson解析            .build();    WebRequestService service = retrofit.create(WebRequestService.class);    Call<NewsInfo> call = service.getRequest();    call.enqueue(new Callback<NewsInfo>() {        @Override        public void onResponse(Call<NewsInfo> call, Response<NewsInfo> response) {            //成功            if (response.isSuccessful() && response.body() != null) {                //解析成功                Log.d("Retrofit", "onResponse: 解析成功");                stories = response.body().getStories();                initDatas();//初始化数据            } else {                //解析失败                Log.d("Retrofit", "onResponse: 解析失败"+response.message()+response.code());            }        }        @Override        public void onFailure(Call<NewsInfo> call, Throwable t) {            //失败            Log.d("TAG", "onFailure: 响应失败");        }    });}

9.数据的显示:
private NewsAdapter newsAdapter;private RecyclerView recyclerView;List<Story> stories;List<String> titleData;List<String> bmpData;
......
oncreate()方法:
init();fillNewsContent();//填充数据RecyclerView.LayoutManager layoutManager = new LinearLayoutManager(this);recyclerView.setLayoutManager(layoutManager);newsAdapter=new NewsAdapter(MainActivity.this,titleData,bmpData);recyclerView.setAdapter(newsAdapter);

初始化:
//初始化数据,填充首页数据private void initDatas() {    Log.d("TAG", "initDatas: ");    for (Story s:stories){        titleData.add(s.getTitle());        if(s.getImages()!=null) {            bmpData.add(s.getImages().get(0));        }else {            bmpData.add("http://pic2.zhimg.com/afecdc04983a8e261326386995150599_t.jpg");        }    }    newsAdapter.notifyDataSetChanged();}private void init() {    recyclerView= (RecyclerView) findViewById(R.id.my_recyclerview);    titleData = new ArrayList<String>();    bmpData = new ArrayList<String>();}

其他代码比较简单,就不上了,关于Retrofit的简单使用就完成了,后面我会深入学习一下更多注解方法和了解。
demo代码:http://download.csdn.net/detail/s1674521/9821572

补充:本文仅做记录和供大家参考,如有不足和改进之处,欢迎指出,谢谢。
1 0