Android开发之Retrofit浅析及初步使用
一、简介
1、官方解释
- A type-safe HTTP client for Android and Java
- 一个针对Android和Java类型安全的http客户端
- 这是官网地址: http://square.github.io/retrofit/
- github地址:https://github.com/square/retrofit
- 写的很好:http://www.jianshu.com/p/a3e162261ab6?utm_campaign=haruki&utm_content=note&utm_medium=reader_share&utm_source=qq
2、白话解释
- Retrofit与okhttp共同出自于Square公司,retrofit就是对okhttp做了一层封装。它是一个可以用于Android和java的网络库,轻松实现网网络请求
3、特点
RESTfun—-REST风格的网络接口
REST全称是Resource Representational State Transfer:通俗来讲就是:资源在网络中以某种表现形式进行状态转移, 描述的是在网络中client和server的一种交互形式;REST本身不实用,实用的是如何设计 RESTful API(REST风格的网络接口);
- 比volley更快
- 支持NIO
- 默认使用OKhttp
- 默认使用Gson解析
4、常用注释接口解释
- @get
- @post
- @header头信息参数
- @path路径信息,替代URL地址中的”{“和”}”部分
- @Query查询参数
@Query查询参数集合
如果Query参数比较多,那么可以通过@QueryMap方式将所有的参数集成在一个Map统一传递,还以上文中的get请求方法为例
public interface BlueService { @GET("book/search") Call<BookSearchResponse> getSearchBooks(@QueryMap Map<String, String> options); }
调用的时候将所有的参数集合在统一的map中即可
Map<String, String> options = new HashMap<>(); map.put("q", "小王子"); map.put("tag", null); map.put("start", "0"); map.put("count", "3"); Call<BookSearchResponse> call = mBlueService.getSearchBooks(options);
@FormUrlEncoded
- @Field
- @FieldMap
- @Multipart
- @PartPost
@BodyPost
接口介绍:http://blog.csdn.net/duanyy1990/article/details/52139294
二、准备
1、添加网络权限
<uses-permission android:name="android.permission.INTERNET"/>
2、测试所用网址
http://www.tngou.net/api/food/show
三、如何使用(五步走)
1、导包
compile 'com.squareup.retrofit2:retrofit:2.1.0'//Retrofit2所需要的包
compile 'com.squareup.retrofit2:converter-gson:2.1.0'//ConverterFactory的Gson依赖包
compile 'com.squareup.retrofit2:converter-scalars:2.1.0'//ConverterFactory的String依赖包
注意:导入的retrofit2包的版本必须要一致,否则就会报错。
2、定义一个接口:封装URL地址和数据请求方式
public interface RequestServes {
@GET("show")
Call<Bean> getMenuById(@Query("id") String id);
}
Retrofit提供的请求方式注解有@GET和@POST,参数注解有@PATH和@Query等。前两个顾名思义就是定义你的请求方式Get、Post,后面的@PATH指的是通过参数填充完整的路径,一般用法:
@GET(“{name}”)
CallgetUser(@Path(“name”) String name);
这里的参数username会被填充至{name}中,形成完整的Url请求地址,{name}相当于一个占位符;
@Query就是我们的请求的键值对的设置,我们构建Call对象的时候会传入此参数,
public interface RequestServes {
@GET("show")
Call<Bean> getMenuById(@Query("id") String id);
}
这里@Query(“id”)就是键,后面的id就是具体的值了,值得注意的是Get和Post请求,都是这样填充参数的;
3、通过一个类,提供Retrofit对象和RequestServes接口服务对象
public class Retrofit {
private RequestServes service;
/**
* 获取Retrofit实例
* @return
*/
public static Retrofit getRetrofit(){
return new Retrofit();
}
/**
* 获取RequestServes实例
* @return
*/
public RequestServes getService(){
return service;
}
private Retrofit() {
retrofit2.Retrofit retrofit = new retrofit2.Retrofit.Builder()
.baseUrl("http://www.tngou.net/api/food/")
.addConverterFactory(GsonConverterFactory.create())
.build();
service = retrofit.create(RequestServes.class);
}
}
- 这里的baseUrl加上之前@GET(“show”)定义的参数形成完整的请求地址;
- addConverterFactory(ScalarsConverterFactory.create())的意思是构建了一个返回支持,如果你的Call对象的泛型接收另外的格式需要添加另外的支持:
//增加返回值为Gson的支持(以实体类返回)
.addConverterFactory(GsonConverterFactory.create())
//增加返回值为Oservable<T>的支持
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
4、在activity中,获取Retrofit和Requestservice对象,并且得到我们的Call对象请求网络(同步异步)
public class MainActivity extends Activity implements View.OnClickListener {
private EditText mEditText;
private TextView mTextView;
private Button bt_query_synchronous;
private Button bt_query_asynchronous;
private RequestServes service;
private Retrofit retrofit;
private String msg;
private String name;
private String keywords;
private Bean result;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
initView();
initRetrofit();
initListener();
}
private void initListener() {
bt_query_asynchronous.setOnClickListener(this);
bt_query_synchronous.setOnClickListener(this);
}
private void initRetrofit() {
retrofit = Retrofit.getRetrofit();
service = retrofit.getService();
}
private void initView() {
setContentView(R.layout.activity_main);
mEditText = (EditText) findViewById(R.id.et_input);
mTextView = (TextView) findViewById(R.id.tv_2);
bt_query_asynchronous = (Button)findViewById(R.id.bt_query_asynchronous);
bt_query_synchronous = (Button)findViewById(R.id.bt_query_synchronous);
}
@Override
public void onClick(View view) {
switch (view.getId()) {
case R.id.bt_query_synchronous:
querySynchronous();
break;
case R.id.bt_query_asynchronous:
queryAsynchronous();
break;
}
}
//同步查询
private void queryAsynchronous() {
String num = mEditText.getText().toString();
if (num.isEmpty()) {
Toast.makeText(MainActivity.this, "请输入ID", Toast.LENGTH_SHORT).show();
return;
}
final Call<Bean> call = service.getMenuById(num);
new Thread(new Runnable() {
@Override
public void run() {
try {
result = call.execute().body();
msg = result.getMessage();
name = result.getName();
keywords = result.getKeywords();
runOnUiThread(new Runnable() {
@Override
public void run() {
mTextView.setText("名称:" + name + "\n关键字:" + keywords + "\n详情:" + msg);
}
});
} catch (IOException e) {
e.printStackTrace();
}
}
}).start();
}
//异步查询
private void querySynchronous() {
String num = mEditText.getText().toString();
if (num.isEmpty()) {
Toast.makeText(MainActivity.this, "请输入ID", Toast.LENGTH_SHORT).show();
return;
}
final Call<Bean> call = service.getMenuById(num);
//异步请求
call.enqueue(new Callback<Bean>() {
@Override
public void onResponse(Call<Bean> call, Response<Bean> response) {
if (response.isSuccessful()) {
Bean result = response.body();//关键
if (result != null) {
String msg = result.getMessage();
String name = result.getName();
String keywords = result.getKeywords();
mTextView.setText("名称:" + name + "\n关键字:"+keywords+"\n详情:" + msg);
}
}
}
@Override
public void onFailure(Call<Bean> call, Throwable t) {
Log.e("TAG", "call==========="+call.toString());
Log.e("TAG", "t============"+t.getLocalizedMessage());
}
});
}
}
5、最后贴上布局
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.metashipanwf.retrofit.MainActivity">
<TextView
android:id="@+id/tv_1"
android:layout_width="wrap_content"
android:layout_height="40dp"
android:layout_alignParentLeft="true"
android:text="ID是:"
android:textColor="#000000"
android:textSize="20sp" />
<EditText
android:id="@+id/et_input"
android:layout_width="180dp"
android:layout_height="40dp"
android:layout_toRightOf="@id/tv_1" />
<Button
android:id="@+id/bt_query_synchronous"
android:layout_width="wrap_content"
android:layout_height="40dp"
android:layout_below="@id/tv_1"
android:text="同步查询" />
<Button
android:id="@+id/bt_query_asynchronous"
android:layout_width="wrap_content"
android:layout_height="40dp"
android:layout_toRightOf="@id/bt_query_synchronous"
android:layout_below="@id/tv_1"
android:text="异步查询" />
<TextView
android:id="@+id/tv_2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignLeft="@id/tv_1"
android:layout_below="@id/bt_query_synchronous"
android:layout_marginTop="20dp"
android:textColor="#000000"
android:textSize="15sp" />
</RelativeLayout>