Android的訪問後臺 API記錄

import retrofit2.Callback;
import retrofit2.Response;

Retrofit是什麼
Retrofit是一個類型安全的HTTP客戶端,支持Android和Java.它是Square公司開源的項目,當前版本2.0。

在實際開發中,我們Retrofit配合OKHTTP來使用。我們使用OKHTTP當做傳輸層,使用Retrofit在OKHTTP之上,使用Java的接口描述我們的HTTP協議。
簡單的說: 使用Retrofit轉換HTTP 的API協議成一個java的Interface服務,我們直接使用java類會方便好多。
Github: https://github.com/square/retrofit
當前版本2.1,本文會對比1.9來講述2.x的特性。Retrofit特點
*
Retrofit將HTTP的API轉換成java接口,並對接口生成默認的實現類。
*
支持同步和異步的調用方式
*
使用註解描述HTTP請求
*
對象轉換,比如從json轉換成java對象
*
支持多請求體(Multipart request body)和文件上傳

類庫和引用添加依賴
在你的應用級別的gradle中添加:

compile ‘com.squareup.retrofit2:retrofit:2.1.0’
一般情況下,我們還需要處理json格式的數據,那麼我們需要一個轉換器,你需要增加下面的依賴:

compile 'com.squareup.retrofit2:converter-gson:2.1.0’集成OKHTTP
爲了避免重複引用OKHTTP,你還可以這麼使用:

compile (‘com.squareup.retrofit2:retrofit:2.1.0’) {
// 排除依賴okhttp
exclude module: ‘okhttp’
}
compile ‘com.squareup.okhttp3:okhttp:3.3.1’ //重新依賴okhttp集成rxJava
如果你還想配合rxJava使用,你需要添加依賴:

compile ‘com.squareup.retrofit2:adapter-rxjava:2.1.0’
compile 'io.reactivex:rxandroid:1.0.1’在Retrofit2.x, RestAdapter 被改變爲 Retrofit
Retrofit 1.9 時的寫法

RestAdapter.Builder builder = new RestAdapter.Builder();
Retrofit 2.x的寫法

Retrofit.Builder builder = new Retrofit.Builder();配置URL地址基礎BaseUrl

基礎url,就是你的服務器的地址,一般是個域名。比如你要訪問 http://www.xxxx.com/user/list
我們在開發中使用相對url,即 /user/list,那麼它的baseUrl就是 http://www.xxx.com
我們這樣設置 baseUrl:

Retrofit retrofit = Retrofit.Builder()
.baseUrl(API_BASE_URL);
.build();

YourService service = retrofit.create(YourService.class);

Retrofit建議我們在設置 baseUrl時,以“/" 結尾。這樣我們在指定相對路徑的時候就不用寫"/"了。
像下面這樣:

public interface UserService {
@POST(“me”) //注意這裏,沒有 斜槓開頭
Callme();
}

Retrofit retrofit = Retrofit.Builder()
.baseUrl(“https://your.api.url/v2/”);//注意這裏,以 斜槓結尾
.build();

UserService service = retrofit.create(UserService.class);

// the request url for service.me() is: // https://your.api.url/v2/me動態的url

有時候我們會以一些其他方式獲得一個url,比如從數據庫或者網絡讀取到一個url,這樣的url就不能像上面那樣 通過 baseUrl和相對url組合而成。
我們可以使用 “@Url” 註解來做,使用"@Url"對一個方法的參數進行註解,表明這是個url,示例:

public interface UserService {
@GET
public Call getZipFile(@Url String url);
}由OKHTTP驅動的攔截器Interceptors

使用攔截器處理自定義請求是一種很有用的方式。步驟:
1.自定義一個攔截器Interceptor
2.自定義一個OkHttpClient,調用 addInterceptor 方法,傳入上面的攔截器
3.在構建Retrofit時, Retrofit.Builder 中,使用 .client() 方法. 傳入OkHttpClient
示例:

OkHttpClient.Builder httpClient = new OkHttpClient.Builder();
httpClient.addInterceptor(new Interceptor() {
@Override
public Response intercept(Chain chain) throws IOException {
Request original = chain.request();

// Customize the request
Request request = original.newBuilder()
.header("Accept", "application/json")
.header("Authorization", "auth-token")
.method(original.method(), original.body())
.build();

Response response = chain.proceed(request);

// Customize or return the response
return response;
}
});

OkHttpClient client = httpClient.build();
Retrofit retrofit = Retrofit.Builder()
.baseUrl(“https://your.api.url/v2/”);
.client(client)
.build();請求的調用。 同步和異步,和終止

Retrofit 1.x 時,在服務接口的聲明中,同步方法需要一個返回值,異步方式需要一個 Callback 的泛型參數作爲最後一個參數。
而在 2.x 時,不再區分同步和異步調用,都被包裹在 一個泛型Call類中。
下面我們從 “接口定義” 和 “調用” 來對比他們的不同。“接口定義”的區別
Retrofit 1.9 時

public interface UserService {
// 同步,有返回值
@POST("/login")
User login();

// 異步 Request,最後一個參數是 Callback 泛型
@POST("/login")
void getUser(@Query String id, Callback cb);
}
而在 Retrofit 2.x 時

public interface UserService {
@POST("/login")
Call<User> login();
}

注意上面返回了一個Call的泛型。2.x不再以參數和返回值的方式區分異步同步的請求。“調用”的區別

Retrofit 1.9 時
同步是直接調用。
而異步需要傳入回調的實現。在實現裏處理成功和失敗的方法。

// 同步
User user = userService.login();

// 異步
userService.login(new Callback<User>() {
@Override
public void success(User user, Response response) {
// handle response
}

@Override
public void failure(RetrofitError error) {
// handle error
}
});

而在 Retrofit 2.x 時
同步是 調用 call.execute() 來獲得結果。
異步是 調用 enqueue方法和傳入回調。注意這裏的回調 是onResponse 方法,不同於上面的成功和失敗的方法。
這裏的是onResponse 方法使用 response.isSuccessful()判斷成功和失敗。如果失敗,使用 errorBody獲得錯誤信息。

// 同步
Call<User> call = userService.login();
User user = call.execute().body();

// 異步
Call<User> call = userService.login();
call.enqueue(new Callback<User>() {
@Override
public void onResponse(Call<User> call, Response<User> response) {
// response.isSuccessful() is true if the response code is 2xx
if (response.isSuccessful()) {
User user = response.body();
} else {
int statusCode = response.code();

// handle request errors yourself
ResponseBody errorBody = response.errorBody();
}
}

@Override
public void onFailure(Call<User> call, Throwable t) {
// handle execution failures like no internet connectivity
}
}

取消/終止請求
在 Retrofit 1.9 是無法終止請求的。而在2.x ,你可以使用 cancel 來終止請求。

Call call = userService.login();
User user = call.execute().body();

// changed your mind, cancel the request
call.cancel();轉換器選擇你需要的轉換器

對比1.9提供默認的json轉換器,Retrofit 2.x以後不在提供默認的轉換器。比如你要使用json解析,
你可以使用gson轉換器,添加庫依賴:

compile ‘com.squareup.retrofit2:converter-gson:2.1.0’
Retrofit支持很多種轉換器類型,根據你的需要,你可以通過gradle引用不同的擴展庫:

Gson: com.squareup.retrofit2:converter-gson:2.1.0Moshi: com.squareup.retrofit2:converter-moshi:2.1.0Jackson: com.squareup.retrofit2:converter-jackson:2.1.0SimpleXML: com.squareup.retrofit2:converter-simplexml:2.1.0ProtoBuf: com.squareup.retrofit2:converter-protobuf:2.1.0Wire: com.squareup.retrofit2:converter-wire:2.1.0
如果上面的轉換器還不夠你使用的話,你可以通過自己實現 Converter.Factory 來自定義轉換器。添加轉換器到Retrofit對象
我們需要手動添加轉換器到Retrofit對象上,使用addConverterFactory方法來添加一個ConverterFactory對象到Retrofit。
*
你可以根據你的需要選擇不同的 轉換器工廠(ConverterFactory).
*
你可以添加一個或者多個ConverterFactory,順序很重要,Retrofit將會按順序使用它,如果失敗,就嘗試使用下一個轉換器。

示例:

Retrofit retrofit = Retrofit.Builder()
.baseUrl(“https://your.api.url/v2/”);
.addConverterFactory(ProtoConverterFactory.create())
.addConverterFactory(GsonConverterFactory.create())
.build();自定義轉換器
請閱讀 Retrofit converter implementations集成 RxJava依賴

Retrofit 1.9 集成了三種請求執行機制: 同步,異步,RxJava。而到了2.x後,僅僅保留了同步和異步機制。
Retrofit 2.x 提供了一種插件擴展的機制支持RxJava。要集成RxJava,你需要添加以下兩個依賴,
第一個依賴是 CallAdapter 它以一種新的方式處理請求。你可以使用 Observable 作爲接口聲明的返回值。
第二個依賴是 AndroidSchedulers 類所需要的,它提供了 在Android主線程的調度方式。

compile ‘com.squareup.retrofit2:adapter-rxjava:2.1.0’
compile 'io.reactivex:rxandroid:1.0.1’使用
在構建Retrofit實例時,通過 addCallAdapterFactory 方法傳入 CallAdapter。

Retrofit retrofit = new Retrofit.Builder()
.baseUrl(baseUrl);
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
.addConverterFactory(GsonConverterFactory.create())
.build();
接口聲明時,返回一個 Observable 泛型對象。

public interface UserService {
@POST("/me")
Observable<User> me();
}

// this code is part of your activity/fragment
Observable<User> observable = userService.me();
observable
.observeOn(AndroidSchedulers.mainThread())
.subscribeOn(Schedulers.io())
.subscribe(new Subscriber<User>() {
@Override
public void onCompleted() {
// 處理完成
}

@Override
public void onError(Throwable e) {
// 處理異常
}

@Override
public void onNext(User user) {
// 處理響應結果
}
});不包含默認日誌

Retrofit 本身沒有提供日誌功能,不過我們可以通過自定義okhttp的攔截器來實現它。你可以閱讀這篇文章:
on how to get back logging into Retrofit 2更新特性 WebSockets
Retrofit不提供 WebSockets 功能,不過OKHTTP提供了 WebSockets支持。

package com.jczb.zky.ydz.presenter;


import android.app.Activity;
import android.widget.Toast;


import com.jczb.zky.ydz.R;
import com.jczb.zky.ydz.net.MyContext;
import com.jczb.zky.ydz.net.bean.ComApi;
import com.jczb.zky.ydz.net.bean.UserModel;
import com.jczb.zky.ydz.view.base.MyApplication;
import com.jczb.zky.ydz.view.ui.impl.ImAppStartActivity;
import com.jczb.zky.ydz.view.ui.impl.ImLoginActivity;
import com.jczb.zky.ydz.view.utils.SaveInfoUtil;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;




/**
* Created by Administrator on 2017/11/6.
*/


public class LoginPresent implements IMLoginPresent {
    private boolean hasStart = false;
    public ImLoginActivity mImLoginAtivity;
    public ImAppStartActivity mImAppStartActivity;


    public LoginPresent(ImAppStartActivity imAppStartActivity) {
        mImAppStartActivity = imAppStartActivity;
    }




    public LoginPresent(ImLoginActivity imLoginActivity) {
        mImLoginAtivity = imLoginActivity;
    }

記錄代碼:

@Override
public void doNetDologin(final Activity view, final String username, final String psw) {
    //查詢後臺請求api
    Call<UserModel> usercall = ComApi.getInstance().doLogin(username,psw,"1");
    usercall.enqueue(new Callback<UserModel>() {
        @Override
        public void onResponse(Call<UserModel> call, final Response<UserModel> response) {
            if (response.isSuccessful() && response.body().getCode()==0) {


                Integer id = response.body().getData().getId();
                String userId = response.body().getData().getUserid();
                String pwd = response.body().getData().getPwd();
                String remarks = response.body().getData().getRemarks();
                String state = response.body().getData().getState();


                SaveInfoUtil.clearAllSPInfo(MyApplication.getContext());
                doStartIntent("0",response.body().getMsg());
                if (mImLoginAtivity != null) {
                    mImLoginAtivity.saveUserLogin(id,userId,pwd,remarks,state);
                }
            }
            else {
                if (mImLoginAtivity != null) {
                    mImLoginAtivity.doButtonAddListener();
                }
                if (response.body() != null) {
                    doStartIntent("1",response.body().getMsg());
                } else {
                    Toast.makeText(MyApplication.getContext(), R.string.serve_failed, Toast.LENGTH_SHORT).show();
                    doStartIntent("2","");
                }
            }
        }


        @Override
        public void onFailure(Call<UserModel> call, Throwable t) {
            Toast.makeText(MyApplication.getContext(), R.string.donet_failed, Toast.LENGTH_SHORT).show();
            if (mImLoginAtivity != null) {
                mImLoginAtivity.doButtonAddListener();
            }
            doStartIntent("2","");
        }
    });
}
//跳轉到首頁
@Override
public void doStartIntent(String type,String msg) {
    if (mImLoginAtivity != null) {
        mImLoginAtivity.startIntent(type,msg);
    }
}

}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章