上一篇文章講述了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,或掃描下面的二維碼: