Retrofit 2.0的简单使用
新手入门的时候原理性的东西太多容易迷糊,反倒效果不好,废话不多说:
以下示例通过 http://ip.taobao.com/service/getIpInfo.php?ip=21.22.11.33 获取json数据。
代码结构.png完整代码地址:https://github.com/hibernate3/RetrofitDemo
环境:JDK 1.8,AndroidStudio 2.2.3
1、通过配置gradle配置将Retrofit框架引入项目
compile 'io.reactivex:rxandroid:1.1.0'
compile 'io.reactivex:rxjava:1.1.0'
compile 'com.squareup.retrofit:retrofit:2.0.0-beta2'
compile 'com.squareup.retrofit:converter-gson:2.0.0-beta2'
compile 'com.squareup.retrofit:adapter-rxjava:2.0.0-beta2'
2、编写API服务代码
package com.example.retrofitdemo.data.api;
import com.example.retrofitdemo.data.api.response.GetIpInfoResponse;
import retrofit.Call;
import retrofit.http.GET;
import retrofit.http.Query;
import rx.Observable;
/**
* Created by Steven on 16/12/16.
*/
public interface ApiService {
@GET("service/getIpInfo.php")
Observable<GetIpInfoResponse> getIpInfo(@Query("ip") String ip);//使用RxJava
// @GET("service/getIpInfo.php")
// Call<GetIpInfoResponse> getIpInfo(@Query("ip") String ip);//不使用RxJava
}
3、定义接收数据的response
package com.example.retrofitdemo.data.api.response;
import com.example.retrofitdemo.data.api.model.IpInfo;
/**
* Created by Steven on 16/12/16.
*/
public class GetIpInfoResponse {
public IpInfo data;
}
4、请求数据并显示
package com.example.retrofitdemo;
import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.ProgressBar;
import android.widget.TextView;
import com.example.retrofitdemo.data.api.ApiService;
import com.example.retrofitdemo.data.api.response.GetIpInfoResponse;
import retrofit.Call;
import retrofit.Callback;
import retrofit.GsonConverterFactory;
import retrofit.Response;
import retrofit.Retrofit;
import retrofit.RxJavaCallAdapterFactory;
import rx.Subscription;
import rx.android.schedulers.AndroidSchedulers;
import rx.schedulers.Schedulers;
import rx.Subscriber;
public class MainActivity extends Activity {
private static final String ENDPOINT = "http://ip.taobao.com";
private TextView mTvContent;
private ProgressBar mProgressBar;
private Button mButton;
private Subscription mSubscription;//用于取消订阅
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mTvContent = (TextView) findViewById(R.id.tv_content);
mProgressBar = (ProgressBar) findViewById(R.id.progress_bar);
mButton = (Button) findViewById(R.id.button_start);
mButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mTvContent.setText("");
mProgressBar.setVisibility(View.VISIBLE);
//=======使用RxJava=======
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(ENDPOINT)
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
.build();
ApiService apiService = retrofit.create(ApiService.class);
mSubscription = apiService.getIpInfo("63.223.108.42")
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Subscriber<GetIpInfoResponse>() {
@Override
public void onCompleted() {
mProgressBar.setVisibility(View.GONE);
}
@Override
public void onError(Throwable e) {
mProgressBar.setVisibility(View.GONE);
mTvContent.setText(e.getMessage());
}
@Override
public void onNext(GetIpInfoResponse getIpInfoResponse) {
mTvContent.setText(getIpInfoResponse.data.country);
}
});
//=======不使用RxJava=======
// Retrofit retrofit = new Retrofit.Builder()
// .baseUrl(ENDPOINT)
// .addConverterFactory(GsonConverterFactory.create())
// .build();
//
// ApiService apiService = retrofit.create(ApiService.class);
//
// Call<GetIpInfoResponse> call = apiService.getIpInfo("63.223.108.42");
// call.enqueue(new Callback<GetIpInfoResponse>() {
// @Override
// public void onResponse(Response<GetIpInfoResponse> response, Retrofit retrofit) {
// mProgressBar.setVisibility(View.GONE);
// GetIpInfoResponse getIpInfoResponse = response.body();
// mTvContent.setText(getIpInfoResponse.data.country);
// }
//
// @Override
// public void onFailure(Throwable t) {
// mProgressBar.setVisibility(View.GONE);
// mTvContent.setText(t.getMessage());
// }
// });
}
});
}
@Override
protected void onDestroy() {
//使用RxJava方式时,需要取消订阅
if (mSubscription != null && mSubscription.isUnsubscribed()){
mSubscription.unsubscribe();
}
}
}
5、取消订阅
正常情况下, 行为结束之后, 到达onComplete()或者onError(), RxJava的订阅会自动取消。但是在处理网络请求的时候, 很可能会出现请求还没有返回, 界面就已经结束了的情况。
订阅方法subscribe()的返回值是一个Subscription对象, 我们保存了这个对象的引用, 然后在onPause()或者onDestroy()的时候取消请求, 防止内存泄露。
关于请求注解
Retrofit提供的请求方式注解有@GET和@POST,参数注解有@PATH和@Query等,我们只介绍常用的;前两个顾名思义就是定义你的请求方式Get or Post,后面的@PATH指的是通过参数填充完整的路径,一般用法:
@GET("{name}")Call<User> getUser(@Path("name") String username);
这里的参数username会被填充至{name}中,形成完整的Url请求地址,{name}相当于一个占位符;
@Query就是我们的请求的键值对的设置,我们构建Call对象的时候会传入此参数,
@POST("mobileLogin/submit.html")
Call<String> getString(@Query("loginname") String loginname,@Query("loginpwd") String loginpwd);
这里@Query("loginname")就是键,后面的loginname就是具体的值了,值得注意的是Get和Post请求,都是这样填充参数的
同步和异步
这里注意用Retrofit请求的返回值是Call<T>或者Observable<T>(RxJava的情形),泛型T是model类型,它有两个方法:
execute()是同步方法, 返回Response<T>
enqueue()是异步方法, 在上面的例子中用的就是这个,在回调onResponse()中返回了Response<T>
Converter
Converter的作用:如果不指定Converter,默认情况下Retrofit只能返回ResponseBody类型,加了Converter之后就可以返回我们定义的Model类型了。所以Converter替我们做了json -> model的工作。
本例子中ConverterFactory指定的是GsonConverterFactory。这里我们选的是Gson Converter,所以依赖的是com.squareup.retrofit2:converter-gson。
Retrofit支持多种converters:
Gson: com.squareup.retrofit2:converter-gson
Jackson: com.squareup.retrofit2:converter-jackson
Moshi: com.squareup.retrofit2:converter-moshi
Protobuf: com.squareup.retrofit2:converter-protobuf
Wire: com.squareup.retrofit2:converter-wire
Simple XML: com.squareup.retrofit2:converter-simplexml
Scalars (primitives, boxed, and String): com.squareup.retrofit2:converter-scalars
用RxJava进行线程切换
例子中.subscribeOn(Schedulers.io())指定Observable的工作, 在我们的例子中Observable的工作即发送请求,在io线程做,指定了被观察者的处理线程;
.observeOn(AndroidSchedulers.mainThread())指定最后onNext()回调在主线程,即指定了通知后续观察者的线程。
关于这两个操作符的更多说明请看官方文档:subscribeOn和observeOn。
转载请说明出处:http://www.jianshu.com/p/951996181289
参考链接:
http://blog.csdn.net/bitian123/article/details/51899716
http://blog.csdn.net/liuhongwei123888/article/details/50375283
http://www.cnblogs.com/mengdd/p/6047948.html