Retrofit使用教程(三) : Retrofit与RxJava初相逢
上一篇文章讲述了Retrofit的基本使用,包括GET,POST等请求.今天的文章中Retrofit要与RxJava配合使用.
了解RxJava
RxJava有种种好处,我不在这里一一讲述.这里我只给出一个使用RxJava的例子.如果想更深入地了解RxJava,可以参考以下文章:
接下来的文章,我也会写RxJava的进一步使用的.
案例说明
该例子是获取手机上安装的APP,然后列表显示包括名称,图标,安装时间等信息.
上代码
下面是自定义的AppInfo
类,包含名称,图标,安装时间,版本号,版本名称等属性.
public class AppInfo {
private String name;
private String installTime;
private int versionCode;
private String versionName;
private Drawable icon;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getInstallTime() {
return installTime;
}
public void setInstallTime(String installTime) {
this.installTime = installTime;
}
public int getVersionCode() {
return versionCode;
}
public void setVersionCode(int versionCode) {
this.versionCode = versionCode;
}
public String getVersionName() {
return versionName;
}
public void setVersionName(String versionName) {
this.versionName = versionName;
}
public Drawable getIcon() {
return icon;
}
public void setIcon(Drawable icon) {
this.icon = icon;
}
@Override
public String toString() {
return "AppInfo{" +
"name='" + name + '\\'' +
", installTime='" + installTime + '\\'' +
", versionCode='" + versionCode + '\\'' +
", versionName='" + versionName + '\\'' +
", icon=" + icon +
'}';
}
}
下面是获取AppLie表的代码,封装为工具类使用:
public class AppUtil {
/**
* 获取已安装的APP的列表
* @param context 上下文
* @return AppInfo列表
*/
public static List<AppInfo> getAppList(Context context){
List<AppInfo> appInfoList = new ArrayList<>();
List<PackageInfo> packages = context.getPackageManager()
.getInstalledPackages(PackageManager.GET_ACTIVITIES);
for (PackageInfo packageInfo : packages) {
AppInfo appInfo = new AppInfo();
appInfo.setName(packageInfo.applicationInfo
.loadLabel(context.getPackageManager())
.toString());
appInfo.setIcon(packageInfo.applicationInfo
.loadIcon(context.getPackageManager()));
appInfo.setInstallTime(getFormatTime(packageInfo.firstInstallTime));
appInfo.setVersionCode(packageInfo.versionCode);
appInfo.setVersionName(packageInfo.versionName);
appInfoList.add(appInfo);
}
return appInfoList;
}
public static String getFormatTime(long time){
if (time <= 0){
return "";
}
return SimpleDateFormat.getDateInstance(DateFormat.FULL).format(new Date(time));
}
}
不使用RxJava怎么做?
我们在不适用RxJava时怎么做?通常新建一个子线程去执行任务,然后回调更新界面,对不对?
private void getByNormal() {
refreshLayout.setRefreshing(true);
infoList.clear();
appAdapter.notifyDataSetChanged();
new AsyncTask<Void, Void, List<AppInfo>>(){
@Override
protected List<AppInfo> doInBackground(Void... params) {
return AppHelper.getHelper().getListByNormal(MainActivity.this);
}
@Override
protected void onPostExecute(List<AppInfo> appInfos) {
infoList.addAll(appInfos);
appAdapter.notifyDataSetChanged();
refreshLayout.setRefreshing(false);
}
};
}
使用RxJava
使用RxJava是这样来写代码的:
1.创建Observable
public Observable<List<AppInfo>> getListByRxJava(final Context context){
Observable<List<AppInfo>> observer = Observable.create(
new Observable.OnSubscribe<List<AppInfo>>() {
@Override
public void call(Subscriber<? super List<AppInfo>> subscriber) {
List<AppInfo> infoList = AppUtil.getAppList(context);
subscriber.onNext(infoList);
subscriber.onCompleted();
}
});
return observer;
}
2.在界面出调用
private void getByRxJava() {
refreshLayout.setRefreshing(true);
infoList.clear();
appAdapter.notifyDataSetChanged();
AppHelper.getHelper().getListByRxJava(this)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Subscriber<List<AppInfo>>() {
@Override
public void onCompleted() {
appAdapter.notifyDataSetChanged();
refreshLayout.setRefreshing(false);
}
@Override
public void onError(Throwable e) {
}
@Override
public void onNext(List<AppInfo> list) {
infoList.addAll(list);
}
});
}
看结果
这个Demo的源码在此:RxJavaDemo
在Retrofit中使用RxJava
上次我们获取手机的归属地时的PhoneService中是这样写的:
@GET("/apistore/mobilenumber/mobilenumber")
Call<PhoneResult> getResult(@Header("apikey") String apikey,
@Query("phone") String phone);
返回了一个Call对象,使用RxJava我们则返回一个可被观测的PhoneResult:Observable,如下:
@GET("/apistore/mobilenumber/mobilenumber")
Observable<PhoneResult> getPhoneResult(@Header("apikey") String apikey,
@Query("phone") String phone);
为了能返回此对象,我们需要在创建Retrofit对象时添加一个RxJava对象的Adapter来自动完成:
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(BASE_URL)
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
.addConverterFactory(GsonConverterFactory.create())
.build();
为此,还封装了一个单例模式的PhoneApi类:
/**
* 手机号相关的API
* Created by Asia on 2016/3/24 0024.
*/
public class PhoneApi {
/**
* HOST地址
*/
public static final String BASE_URL = "http://apis.baidu.com";
/**
* 开发者Key
*/
public static final String API_KEY = "8e13586b86e4b7f3758ba3bd6c9c9135";
/**
* 获取PhoneApi实例
* @return
*/
public static PhoneApi getApi(){
return ApiHolder.phoneApi;
}
static class ApiHolder{
private static PhoneApi phoneApi = new PhoneApi();
}
private PhoneService service;
private PhoneApi(){
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(BASE_URL)
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
.addConverterFactory(GsonConverterFactory.create())
.build();
service = retrofit.create(PhoneService.class);
}
/**
* 获取PhoneService实例
* @return
*/
public PhoneService getService(){
return service;
}
}
下面就是使用去获取手机的归属地啦:
phoneService.getPhoneResult(PhoneApi.API_KEY, number)
.subscribeOn(Schedulers.newThread()) //子线程访问网络
.observeOn(AndroidSchedulers.mainThread()) //回调到主线程
.subscribe(new Observer<PhoneResult>() {
@Override
public void onCompleted() {}
@Override
public void onError(Throwable e) {}
@Override
public void onNext(PhoneResult result) {
if (result != null && result.getErrNum() == 0) {
PhoneResult.RetDataEntity entity = result.getRetData();
resultView.append("地址:" + entity.getCity());
}
}
});
}
运行一下吧,结果是同样的哈.
项目地址在此:Dev-Wiki/RetrofitDemo
更多文章请移步我的博客:DevWiki Blog
重要说明
想随时获取最新博客文章更新,请关注公共账号DevWiki,或扫描下面的二维码: