讲述了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 ListgetAppList(Context context){ List appInfoList = new ArrayList<>(); List 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>(){ @Override protected List doInBackground(Void... params) { return AppHelper.getHelper().getListByNormal(MainActivity.this); } @Override protected void onPostExecute(List appInfos) { infoList.addAll(appInfos); appAdapter.notifyDataSetChanged(); refreshLayout.setRefreshing(false); } }; }
使用RxJava
使用RxJava是这样来写代码的:
1.创建Observable
public Observable
> getListByRxJava(final Context context){ Observable
> observer = Observable.create( new Observable.OnSubscribe
>() { @Override public void call(Subscriber > subscriber) { List 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
>() { @Override public void onCompleted() { appAdapter.notifyDataSetChanged(); refreshLayout.setRefreshing(false); } @Override public void onError(Throwable e) { } @Override public void onNext(List list) { infoList.addAll(list); } }); }
看结果
这个Demo的源码在此:
在Retrofit中使用RxJava
上次我们获取手机的归属地时的PhoneService
中是这样写的:
@GET("/apistore/mobilenumber/mobilenumber") CallgetResult(@Header("apikey") String apikey, @Query("phone") String phone);
返回了一个Call对象,使用RxJava我们则返回一个可被观测的PhoneResult
:Observable<PhoneResult>
,如下:
@GET("/apistore/mobilenumber/mobilenumber") ObservablegetPhoneResult(@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() { @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()); } } });}
运行一下吧,结果是同样的哈.
项目地址在此:
更多文章请移步我的博客:
重要说明
想随时获取最新博客文章更新,请关注公共账号DevWiki,或扫描下面的二维码: