上一篇文章讲述了Retrofit的基本使用,包括GET,POST等请求.今天的文章中Retrofit要与RxJava配合使用.

了解RxJava

RxJava有种种好处,我不在这里一一讲述.这里我只给出一个使用RxJava的例子.



接下来的文章,我也会写RxJava的进一步使用的.

案例说明

该例子是获取手机上安装的APP,然后列表显示包括名称,图标,安装时间等信息.

上代码

下面是自定义的​​AppInfo​​类,包含名称,图标,安装时间,版本号,版本名称等属性.


[代码]java代码:


010203040506070809101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263

​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表的代码,封装为工具类使用:


[代码]java代码:


010203040506070809101112131415161718192021222324252627282930313233

​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));​​​​    ​​​​}​​​​}</packageinfo></appinfo></appinfo>​



不使用RxJava怎么做?

我们在不适用RxJava时怎么做?通常新建一个子线程去执行任务,然后回调更新界面,对不对?


[代码]java代码:


01020304050607080910111213141516171819

​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​​​​);​​​​        ​​​​}​​​​    ​​​​};​​​​}</appinfo></appinfo></​​​​void​​​​,>​



使用RxJava

使用RxJava是这样来写代码的:

1.创建​​Observable​


[代码]java代码:


010203040506070809101112

​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;​​​​}</appinfo></list<appinfo></list<appinfo></list<appinfo>​



2.在界面出调用


[代码]java代码:


01020304050607080910111213141516171819202122232425

​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);​​​​                ​​​​}​​​​            ​​​​});​​​​}</appinfo></list<appinfo>​



看结果

这个Demo的源码在此:​​RxJavaDemo​

在Retrofit中使用RxJava

上次我们获取手机的归属地时的​​PhoneService​​中是这样写的:


[代码]java代码:


123

​@GET​​​​(​​​​"/apistore/mobilenumber/mobilenumber"​​​​)​​​​Call<phoneresult> getResult(​​​​@Header​​​​(​​​​"apikey"​​​​) String apikey,​​​​                            ​​​​@Query​​​​(​​​​"phone"​​​​) String phone);</phoneresult>​



返回了一个Call对象,使用RxJava我们则返回一个可被观测的​​PhoneResult​​​:​​Observable<PhoneResult>​​,如下:


[代码]java代码:


123

​@GET​​​​(​​​​"/apistore/mobilenumber/mobilenumber"​​​​)​​​​Observable<phoneresult> getPhoneResult(​​​​@Header​​​​(​​​​"apikey"​​​​) String apikey,​​​​                                       ​​​​@Query​​​​(​​​​"phone"​​​​) String phone);</phoneresult>​



为了能返回此对象,我们需要在创建Retrofit对象时添加一个RxJava对象的Adapter来自动完成:


[代码]java代码:


12345

​Retrofit retrofit = ​​​​new​​​​Retrofit.Builder()​​​​        ​​​​.baseUrl(BASE_URL)​​​​        ​​​​.addCallAdapterFactory(RxJavaCallAdapterFactory.create())​​​​        ​​​​.addConverterFactory(GsonConverterFactory.create())​​​​        ​​​​.build();​



为此,还封装了一个单例模式​的​​PhoneApi​​类:


[代码]java代码:


01020304050607080910111213141516171819202122232425262728293031323334353637383940414243444546

​/**​​​​ ​​​​* 手机号相关的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;​​​​    ​​​​}​​​​}​



下面就是使用去获取手机的归属地啦:


[代码]java代码:


01020304050607080910111213141516171819

​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());​​​​                ​​​​}​​​​            ​​​​}​​​​        ​​​​});​​​​}</phoneresult>​



运行一下吧,结果是同样的哈.