上一篇文章讲述了Retrofit的基本使用,包括GET,POST等请求.今天的文章中Retrofit要与RxJava配合使用.java
RxJava有种种好处,我不在这里一一讲述.这里我只给出一个使用RxJava的例子.若是想更深刻地了解RxJava,能够参考如下文章:git
接下来的文章,我也会写RxJava的进一步使用的.api
该例子是获取手机上安装的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表的代码,封装为工具类使用:app
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时怎么作?一般新建一个子线程去执行任务,而后回调更新界面,对不对?ide
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是这样来写代码的:工具
1.建立Observable
post
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
上次咱们获取手机的归属地时的PhoneService
中是这样写的:
@GET("/apistore/mobilenumber/mobilenumber") Call<PhoneResult> getResult(@Header("apikey") String apikey, @Query("phone") String phone);
返回了一个Call对象,使用RxJava咱们则返回一个可被观测的PhoneResult
:Observable<PhoneResult>
,以下:
@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,或扫描下面的二维码: