Android Retrofit使用教程(三):Retrofit與RxJava初相逢

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

瞭解RxJava

RxJava有種種好處,我不在這裏一一講述.這裏我只給出一個使用RxJava的例子.java

 

 

接下來的文章,我也會寫RxJava的進一步使用的.git

案例說明

該例子是獲取手機上安裝的APP,而後列表顯示包括名稱,圖標,安裝時間等信息.github

上代碼

下面是自定義的AppInfo類,包含名稱,圖標,安裝時間,版本號,版本名稱等屬性.api

[代碼]java代碼:

?
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
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代碼:

?
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
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時怎麼作?一般新建一個子線程去執行任務,而後回調更新界面,對不對?app

[代碼]java代碼:

?
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
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是這樣來寫代碼的:ide

1.建立Observable工具

[代碼]java代碼:

?
01
02
03
04
05
06
07
08
09
10
11
12
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.在界面出調用ui

[代碼]java代碼:

?
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
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代碼:

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

 

返回了一個Call對象,使用RxJava咱們則返回一個可被觀測的PhoneResult:Observable<PhoneResult>,以下:

[代碼]java代碼:

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

 

爲了能返回此對象,咱們須要在建立Retrofit對象時添加一個RxJava對象的Adapter來自動完成:

[代碼]java代碼:

?
1
2
3
4
5
Retrofit retrofit = new Retrofit.Builder()
         .baseUrl(BASE_URL)
         .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
         .addConverterFactory(GsonConverterFactory.create())
         .build();

 

爲此,還封裝了一個單例模式PhoneApi類:

[代碼]java代碼:

?
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
/**
  * 手機號相關的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代碼:

?
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
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>

 

運行一下吧,結果是一樣的哈.

相關文章
相關標籤/搜索