1. 程式人生 > >OKhttp、RXjava與retrofit的網路訪問使用

OKhttp、RXjava與retrofit的網路訪問使用

兩個月沒有寫微博了,無論如何,現在再次迴歸Android的打怪升級。

關於Rxjava的學習和介紹,有興趣的可以去雲盤中提取pdf資料,這裡不做詳解,地址和提取碼如下:連結:http://pan.baidu.com/s/1skDOjN3 密碼: ajv7。

要想Rxjava和Retrofit結合使用,我們先簡單瞭解一下什麼是Retrofit:Square提供的開源產品,為Android平臺的應用提供一個型別安全的REST客戶端。


只使用Retrofit來訪問網路: 1.準備:此處模擬網路返回的資料格式為JSON,這裡使用fastjson來做為解析工具(Android自帶的JSON解析工具功能沒有那麼強大,有可能會引發問題,不推薦使用)
,引入此jar包,要使用Retrofit需在gradle引入依賴:compile 'com.squareup.retrofit2:retrofit:2.0.2'

2.Activity中設定點選事件,用於進行網路請求,請求地址和內容請自行配置,此處使用本人設定的地址和資料: private static final String ENDPOINT = "http://192.168.105.XXX:7072/TQA/API/MoblieAPI/"
case R.id.tv_retrofit:
    retrofitTest("78a5bcc7-0a97-44db-a430-0b1a1db422f2",this);  //傳入UserID
    break;

3.API:網路請求的資料傳輸和方法
public interface ApiService {
    @GET("GetUserInfo")
    Call<JSONObject> getUserInfo(@Query("userId") String UserID);
}

4.DTO:資料儲存物件
public class ClassInfoDto implements Serializable {
    private String UserId;
    private String UserName;
    private String EchoName;
    private int Sex;
    private String Photo;
    private String Phone;
    private String WorkNo;  
   //根據返回的資料設定資料儲存物件,此處省略GET和SET方法的程式碼
}

5.Retrofit實現方法,把返回的JSON資料存入一個JSONObject中,然後進行解析
private void retrofitTest(final String userId, final Context context){
    Retrofit lRetrofit = new Retrofit.Builder().baseUrl(ENDPOINT)
            .addConverterFactory(GsonConverterFactory.create()).build(); //生成Retrofit物件
    final ApiService lApiService = lRetrofit.create(ApiService.class); //生成例項
    Call<JSONObject> lHttpResultDtoCall = lApiService.getUserInfo(userId); //請求封裝
    lHttpResultDtoCall.enqueue(new Callback<JSONObject>() {  //請求結果返回
        @Override
        public void onResponse(Call<JSONObject> call, Response<JSONObject> response) {
            JSONObject result = response.body();
            int code = result.getInteger("Code");
            //返回Code為0的時候表示有資料返回
            if(code == 0){
                JSONObject jsonObject = result.getJSONObject("Data");
                if(!TextUtils.isEmpty(jsonObject.toString()) && jsonObject.toString() !=null) {
                    ClassInfoDto lClassInfoDto = JSON.parseObject(jsonObject.toString(),ClassInfoDto.class);
                    mTextView.setText(lClassInfoDto.getEchoName());  //把返回的資料顯示到的View中
                }
            }else {
                //伺服器端給出的異常資訊
                Log.d("retrofit","msg = "+result.getString("Message"));
            }
        }
        @Override
        public void onFailure(Call<JSONObject> call, Throwable t) {
            //異常處理塊
            Log.d("retrofit","e = "+t.toString());
        }
    });
}


對retrofit的使用方法有一定了解後,來看看如何結合Rxjava與retrofit來訪問網路:此處依然是使用fastJSON解析

1、將RxJava、RxAndroid引入專案中:compile 'io.reactivex:rxandroid:1.1.0'  

                                                              compile 'io.reactivex:rxjava:1.1.0'  

compile 'io.reactivex:rxandroid:1.1.0'
compile 'io.reactivex:rxjava:1.1.0'

2、修改ApiService類如下

package com.example.lanzheng.retrofit;
  
import retrofit.Call;  
import retrofit.http.GET;  
import retrofit.http.Query;  
import rx.Observable;  
 /**
 * Created by lan.zheng on 2016/7/26.
 */
public interface ApiService {
    @GET("GetUserInfo")
    Call<JSONObject> getUserInfo(@Query("userId") String UserID);


    /**
     * @param UserID
     * @return
     */
    @GET("GetUserInfo")
    Observable<JSONObject> getUserInfoNew(@Query("userId") String UserID);  //RxJava和Retrofit
}



3、Activity類如下:public class RxjavaTestActivity extends AppCompatActivity implements View.OnClickListener,ManagerTest.TestListener

 @Override
    public void onClick(View view) {
        switch (view.getId()){
            case R.id.tv_rxjava_and_retrofit:
                //設定要傳入的資料
                String userId = "78a5bcc7-0a97-44db-a430-0b1a1db422f2";
                //拿到Retrofit物件並獲得訪問API例項
                 ApiService lApiService = ManagerTest.getManagerTestInstance().initRetrifit().create(lApiService.class);
                //然後獲得網路訪問物件Observable
                Observable<JSONObject> lObservable = lApiService .getUserInfoNew(userId);
                //真正去網路訪問,獲得結果,結果在下面的回撥中顯示
                ManagerTest.getManagerTestInstance().getUserInfoUseRxjava(this,lObservable);
                break;
            default:
                break;
        }
    }

  @Override
    public void getUserData(String s) {
        Log.d("rxjavafortest","getUserData = "+s);  //成功回撥
    }


    @Override
    public void failed(String s) {
        Log.d("rxjavafortest","getUserData = "+s);  //失敗回撥
    }


4.接下來是真正的網路訪問實現環節,這裡我先建立了一個BaseManager基類,這個類有兩個方法,一個用於生成Retrofit物件,一個用於返回網路請求的結果Observable

/**
 * Created by lan.zheng on 2016/7/21.
 */
public class BaseManager {
    public static Retrofit mRetrofit;  //靜態物件
    private static final int sTimeout = 40;
    private static final String URI = "http://192.168.105.192:7072/TQA/API/MoblieAPI/";

    //生成Retrofit物件
    private static void getRetrofit() {
        if (mRetrofit == null) {
            OkHttpClient.Builder builder = new OkHttpClient.Builder();

            //  Log資訊攔截器
            if (BuildConfig.DEBUG) {
                HttpLoggingInterceptor loggingInterceptor = new HttpLoggingInterceptor();
                loggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
                //設定 Debug Log 模式
                builder.addInterceptor(loggingInterceptor);
            }

            //設定超時時間
            builder.connectTimeout(sTimeout, TimeUnit.SECONDS);
            builder.readTimeout(sTimeout, TimeUnit.SECONDS);

            //錯誤重連
            builder.retryOnConnectionFailure(true);

            OkHttpClient okHttpClient = builder.build();
            mRetrofit = new Retrofit.Builder()
                    .baseUrl(URI)
                    //設定 Json 轉換器
                    .addConverterFactory(GsonConverterFactory.create())
                    //RxJava 介面卡
                    .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
                    .client(okHttpClient)
                    .build();
        }
//        return mRetrofit;
    }
    //獲得結果物件返回
    public Observable<JSONObject> getDataBack(Observable<JSONObject> lObservable){
        Observable<JSONObject> lJSONObjectObservable = Observable.just(lObservable)
                .observeOn(Schedulers.io())    //切換到排程器IO去伺服器獲取資料
                .flatMap(new Func1<Observable<JSONObject>, Observable<JSONObject>>() {
                    @Override
                    public Observable<JSONObject> call(final Observable<JSONObject> httpResultObservable) {
                        return httpResultObservable.flatMap(new Func1<JSONObject, Observable<JSONObject>>() {

                            @Override
                            public Observable<JSONObject> call(final JSONObject httpResult) {
//                                Observable.error();  //也可以在這裡除了異常
                                return Observable.create(new Observable.OnSubscribe<JSONObject>(){
                                    @Override
                                    public void call(Subscriber<? super JSONObject> subscriber) {
                                        Log.d("rxjavafortest-result",httpResult.toString());  //獲得JSON資料{"Code":0,"Data":{...},"Message":""}
                                        if(TextUtils.isEmpty(httpResult.toString())  ){
                                            subscriber.onError(new CustomerException("無返回結果"));
                                            return;
                                        }
                                        int code = 0;
                                        String msg = "";
                                            code = httpResult.getInteger("Code");
                                            msg = httpResult.getString("Message");

                                        if(code != 0){
                                            subscriber.onError(new CustomerException(msg));
                                            return;
                                        }
                                        if(TextUtils.isEmpty(httpResult.getString("Data")) || httpResult.getString("Data") == null){
                                            subscriber.onError(new CustomerException("Data為空"));
                                            return;
                                        }
                                        subscriber.onNext(httpResult.getJSONObject("Data"));
                                        subscriber.onCompleted();

                                    }
                                });
                            }
                        });
                    }
                }).unsubscribeOn(Schedulers.io());  //執行結果出來後切換回主執行緒去分發結果
        return lJSONObjectObservable;
    }
 }


5.實現類繼承上面的基類(類名為ManagerTest extendsBaseManager),並宣告一個內部介面用於結果回撥,類的內容如下:

//單例模式,例項化本類
  public static class ManagerBuild{   //例項化本類
        private static final ManagerTest Instance = new ManagerTest();
    }
    
    public static ManagerTest getManagerTestInstance(){
          //生成retrofit例項的時候
        return ManagerBuild.Instance;
    }

    public Retrofit initRetrofit(){   //生成Retrofit物件
         getRetrofit();    return mRetrofit;
    }
    private static TestListener testListener;
    //用於介面回撥
    interface TestListener{
        void getUserData(String s);
        void failed(String s);
    }
 //只要是返回型別都是JSON的都可以用這段程式碼拿到最終結果
    public void getUserInfoUseRxjava(TestListener t,Observable<JSONObject> lObservable){
        testListener = t;  //回撥例項
        Log.d("rxjavafortest","getUserInfoUseRxjava()");
        //結果返回
        getDataBack(lObservable).subscribe(new Subscriber<JSONObject>()
                {
                    @Override
                    public void onCompleted() {

                    }

                    @Override
                    public void onError(Throwable e) {
                        testListener.failed(e.toString());
                    }

                    @Override
                    public void onNext(JSONObject string) {
                        ClassInfoDto lClassInfoDto = JSON.parseObject(string.toString(),ClassInfoDto.class);
                        testListener.getUserData(lClassInfoDto.getWorkNo());
                    }
                });
    }