1. 程式人生 > >rxjava+rxandroid+retrofit2.0使用方法demo講解

rxjava+rxandroid+retrofit2.0使用方法demo講解

最近看了retrofit框架,比較新的網路訪問請求框架,很多專案都涉及到,所以學習了一下,做個總結。
第一講 retrofit2.0單獨使用
1、匯入依賴jar包(也可能是library,反正studio會自動下載)
compile ‘io.reactivex:rxandroid:1.1.0’
compile ‘io.reactivex:rxjava:1.1.0’
compile ‘com.squareup.retrofit:retrofit:2.0.0-beta2’
compile ‘com.squareup.retrofit:converter-gson:2.0.0-beta2’
compile ‘com.squareup.retrofit:adapter-rxjava:2.0.0-beta2’
2、建立訪問網路介面(其實就是構造utl)
public interface GitHubApi {
@GET(“repos/{owner}/{repo}/contributors”)
Call get(@Path(“owner”) String owner, @Path(“repo”) String repo);
}
這裡面使用了註解程式碼,大家可以自行百度學習一下。
主要有:
@path
@GET
@POST
@QUERY
@QUERYMAP

簡單來說,就是構造網路訪問的url
這裡面
Call 方法(引數);
Call 方法();
T:返回的資料型別
這個是固定模板。
當然,
如果結合使用了rxjava,模板也可以是:
Observable 方法(XXX);

3、使用Call.enqueue訪問網路
訪問網路耗時操作,通常放線上程中執行,你可以自己
new Thread(){run()}.start() ,
其實retrofit已經封裝了執行緒請—enqueue( )
button.setOnClickListener( new View.OnClickListener() {
@Override
public void onClick(View v) {
Retrofit retrofit = new Retrofit.Builder()
.baseUrl( “

https://api.github.com/” )
.build();
GitHubApi repo = retrofit.create( GitHubApi.class );//拿到介面物件,反射代理機制
Call call = repo.get( “square”, “retrofit” );//get方法已經被重寫了
//使用call進行請求
call.enqueue( new Callback() {
@Override
public void onResponse(Response response, Retrofit retrofit) {
try {
response.body().string()—” + response.body().string() );
}
} catch (IOException e) {
Log.d( “lihui”, “e—” + e.toString() );
e.printStackTrace();
}
}
@Override
public void onFailure(Throwable t) {
Log.d( “lihui”, “t—” + t.toString() );
}
} );
分析:
call.enqueue( )這個是非同步請求。
call也支援同步請求,
Call call = repo.get();
ResponseBody responseBody= call.execute();
這裡:call.execute()返回物件模板關係

Call<T>

T t=call.execute();
但是android會丟擲異常
阻塞執行緒,因此你不能在安卓的主執行緒中呼叫,不然會面臨NetworkOnMainThreadException。如果你想呼叫execute方法,請在後臺執行緒執行。

如果返回的資料是json格式,
可以對response.body()返回的資料進行反序列化,
使用json包
compile ‘com.google.code.gson:gson:2.3’

 Gson gson = new Gson();
                            ArrayList<Contributor> contributorsList = gson.fromJson( response.body().string(), new TypeToken<List<Contributor>>() {
                            }.getType() );

Contributor實體類,對應

public class Contributor {
    private String login;
    private String contributions;
    private String html_url;
    private String avatar_url;
    public String getAvatar_url() {
        return avatar_url;
    }

    public void setAvatar_url(String avatar_url) {
        this.avatar_url = avatar_url;
    }


    public Contributor(String login) {
        this.login = login;
    }

    public String getHtml_url123() {
        return html_url;
    }

    public void setHtml_url123(String html_url) {
        this.html_url = html_url;
    }


    public String getLogin() {
        return login;
    }

    public void setLogin(String login) {
        this.login = login;
    }

    public String getContributions() {
        return contributions;
    }

    public void setContributions(String contributions) {
        this.contributions = contributions;
    }
}

這裡面的屬性名稱一定要和json中name一致!!!!

其實retrofit中已經有了json轉化器,自動將返回的json格式資料進行序列化。
修改:

 @GET("repos/{owner}/{repo}/contributors")
 Call<List<Contributor>> get(@Path("owner") String owner, @Path("repo") String repo);
 Retrofit retrofit = new Retrofit.Builder().baseUrl( "https://api.github.com/" ).
**addConverterFactory**( GsonConverterFactory.create() ).build();

addConverterFactory:轉化器
對應jar包:
compile ‘com.squareup.retrofit:converter-gson:2.0.0-beta2’

返回處理:

public void onResponse(Response<List<Contributor>> response, Retrofit retrofit) {
                        List<Contributor> contributors = response.body();//已經向返回的資料進行了序列化

                        for (Contributor contributor : contributors) {
                            Log.d( "lihui", "1---" + contributor.getLogin() );
                            Log.d( "lihui", "2---" + contributor.getContributions() );
                            Log.d( "lihui", "3---" + contributor.getHtml_url123() );
                        }
                    }

4、結合rxjava+rxandroid
修改如下:
1)jar包
compile ‘com.squareup.retrofit:adapter-rxjava:2.0.0-beta2’
介面卡
2)@GET("repos/{owner}/{repo}/contributors")
rx.Observable<List<Contributor>> getSource(@Path("owner") String owner, @Path("repo") String repo);

模板2,返回物件Observable

  Retrofit retrofit = new Retrofit.Builder().baseUrl( "https://api.github.com/" ).                                                   addCallAdapterFactory( **RxJavaCallAdapterFactory**.create() ).                                               addConverterFactory( GsonConverterFactory.create() ).build();

注:
addCallAdapterFactory新增適配工廠,這樣rxjava中可以直接傳遞List物件了。

 button3.setOnClickListener( new View.OnClickListener() {
                                        @Override
                                        public void onClick(View v) {
                                            Retrofit retrofit = new Retrofit.Builder().baseUrl( "https://api.github.com/" ).
                                                    addCallAdapterFactory( RxJavaCallAdapterFactory.create() ).                                                    addConverterFactory( GsonConverterFactory.create() ).build();
   GitHubApi mGitHubService = retrofit.create( GitHubApi.class );                                          mGitHubService.getSource( "square", "retrofit" ).subscribeOn( Schedulers.io() ).observeOn( AndroidSchedulers.mainThread() ).subscribe( new Observer<List<Contributor>>() {
                          @Override
           public void onCompleted() {}
                     @Override
                public void onError(Throwable e) {}
       @Override
        public void onNext(List<Contributor> contributors) {
  for (Contributor c : contributors) {
         Log.d( "lihui", "Contributions---" + c.getContributions() );
                                                    }
                                                }
                                            } );
                                        }
                                    }
        );

注:
addCallAdapterFactory
返回的資料可以結合rxjava的Observeble資料傳遞下去。

2016-12-1 筆記:
retrofit結合使用rxjava,
必須新增
.addCallAdapterFactory( RxJavaCallAdapterFactory.create() )
否則出現異常:

 E/AndroidRuntime: FATAL EXCEPTION: main
                                                                            Process: com.example.lihui20.testhttp, PID: 6397
                                                                            java.lang.IllegalArgumentException: *Unable to create call adapter for* rx.Observable<com.squareup.okhttp.ResponseBody>
                                                                                for method GitHubApi.getLocation
                                                                                at retrofit.Utils.methodError(Utils.java:177)
                                                                                at retrofit.MethodHandler.createCallAdapter(MethodHandler.java:47)
                                                                                at retrofit.MethodHandler.create(MethodHandler.java:26)
                                                                                at retrofit.Retrofit.loadMethodHandler(Retrofit.java:151)
                                                                                at retrofit.Retrofit$1.invoke(Retrofit.java:132)
                                                                                at java.lang.reflect.Proxy.invoke(Proxy.java:813)
                                                                                at $Proxy0.getLocation(Unknown Source)
                                                                                at com.example.lihui20.testhttp.MainActivity$4.onClick(MainActivity.java:161)
                                                                                at android.view.View.performClick(View.java:5609)
                                                                                at android.view.View$PerformClick.run(View.java:22279)
                                                                                at android.os.Handler.handleCallback(Handler.java:751)
                                                                                at android.os.Handler.dispatchMessage(Handler.java:95)
                                                                                at android.os.Looper.loop(Looper.java:154)
                                                                                at android.app.ActivityThread.main(ActivityThread.java:6111)
                                                                                at java.lang.reflect.Method.invoke(Native Method)
                                                                                at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:865)
                                                                                at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:755)
                                                                             Caused by: java.lang.IllegalArgumentException: Could not locate call adapter for rx.Observable<com.squareup.okhttp.ResponseBody>. Tried:
                                                                             * retrofit.ExecutorCallAdapterFactory
                                                                                at retrofit.Retrofit.nextCallAdapter(Retrofit.java:207)
                                                                                at retrofit.Retrofit.callAdapter(Retrofit.java:175)
                                                                                at retrofit.MethodHandler.createCallAdapter(MethodHandler.java:45)
                                                                                    ... 15 more

java.lang.IllegalArgumentException: Unable to create call adapter for rx.Observable

Call<ResponseBody>

結果返回不是json格式,我們想轉換成其他型別,如:
Call

  Process: com.example.lihui20.testhttp, PID: 11899
                                                                              java.lang.IllegalArgumentException: **Unable to create converter for class java.lang.String**
                                                                                  for method GitHubApi.getLocation
                                                                                  at retrofit.Utils.methodError(Utils.java:177)
                                                                                  at retrofit.MethodHandler.createResponseConverter(MethodHandler.java:57)
                                                                                  at retrofit.MethodHandler.create(MethodHandler.java:29)
                                                                                  at retrofit.Retrofit.loadMethodHandler(Retrofit.java:151)
                                                                                  at retrofit.Retrofit$1.invoke(Retrofit.java:132)
                                                                                  at java.lang.reflect.Proxy.invoke(Proxy.java:813)
                                                                                  at $Proxy0.getLocation(Unknown Source)
                                                                                  at com.example.lihui20.testhttp.MainActivity$4.onClick(MainActivity.java:162)
                                                                                  at android.view.View.performClick(View.java:5609)
                                                                                  at android.view.View$PerformClick.run(View.java:22279)
                                                                                  at android.os.Handler.handleCallback(Handler.java:751)
                                                                                  at android.os.Handler.dispatchMessage(Handler.java:95)
                                                                                  at android.os.Looper.loop(Looper.java:154)
                                                                                  at android.app.ActivityThread.main(ActivityThread.java:6111)
                                                                                  at java.lang.reflect.Method.invoke(Native Method)
                                                                                  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:865)
                                                                                  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:755)
                                                                               Caused by: java.lang.IllegalArgumentException: Could not locate ResponseBody converter for class java.lang.String. Tried:
                                                                               * retrofit.BuiltInConverters
                                                                                  at retrofit.Retrofit.responseConverter(Retrofit.java:266)
                                                                                  at retrofit.MethodHandler.createResponseConverter(MethodHandler.java:55)
                                                                                    ... 15 more

自定義
converter for class java.lang.String

 .addConverterFactory( new Converter.Factory() {
                            @Override
                            public Converter<ResponseBody, ?> fromResponseBody(Type type, Annotation[] annotations) {

                                return new Converter<ResponseBody, String>() {
                                    @Override
                                    public String convert(ResponseBody value) throws IOException {
                                        return value.string();
                                    }

                                };
                            }
                        } )

rxjava運算子學習:
1)just和from
直接上例子

  List<Integer> list2 = new ArrayList<Integer>();
                list2.add( 123 );
                list2.add( 34 );
                Observable.from( list2  ).subscribe( new Action1<Integer>() {
                    @Override
                    public void call(Integer integer) {
                        Log.d("lihui","from---"+ integer);

                    }
                } );
分析:
call方法會連續呼叫多次,迴圈把list中item輸出。
12-02 17:04:31.958 13858-13858/com.example.lihui20.testhttp D/lihui: from---123
12-02 17:04:31.958 13858-13858/com.example.lihui20.testhttp D/lihui: from---34

                Observable.just(list2 ).subscribe( new Action1<List<Integer>>() {
                    @Override
                    public void call(List<Integer> integers) {
                        Log.d("lihui","just---"+ integers.toString() );
                    }
                } );

分析:
修改call方法—
直接傳遞
List integers 物件
自定義的
public void call(List integers)
呼叫一次。