認證android retrofit,Retrofit之項目介紹

項目介紹

官網對retrofit介紹是這是一個"類型安全(type-safe)"的Android/Java http客戶端. 目前retrofit的最新正式版本為1.9.0. 2.0版本預計2015年底發布, 相較于之前版本, 2.0版本在架構上做了很大改變, 本文代碼相關的內容都是基于retrofit2.0-beta2.

注: 在編程語言的語法中, type-safe通常指編譯器在編譯時檢查變量的類型, 如果試圖向?變量分配一個錯誤的類型,編譯器就會報錯.

在項目中使用retrofit

retrofit庫可以在maven.org?找到. 可以直接添加到maven或gradle工程中.Maven #+BEGIN_SRC xml

com.squareup.retrofitretrofit2.0.0-beta2 #+END_EXAMPLEGradle. 如果與服務端的請求和結果都是json的話,需要gson converter進行轉化, 因為要把該庫也添加上. #+BEGIN_SRC xml compile 'com.squareup.retrofit:retrofit:2.0.0-beta2' compile 'com.squareup.retrofit:converter-gson:2.0.0-beta2' #+END_EXAMPLE

混淆配置 如果項目中使用混淆的話, 需要在混淆文件中假如如下配置-dontwarn?retrofit.**-keep?class?retrofit.**?{?*;?}-keepattributes?Signature-keepattributes?Exceptions

程序示例

一個簡單的retrofit程序

場景:通過GET請求向服務器返回用戶信息, 服務器通過Json格式返回一個或多個用戶的信息. 基于這個例子介紹一下retrofit的使用步驟:用戶類. 這段代碼定義了用戶類User, 每個用戶包含三個基本信息:id, name, age; 通過retrofit請求用戶信息時, 客戶端返回用戶的json信息, retrofit可以直接將json信息轉化為用戶類.public?class?User?{

private?int?id;

private?String?name;

private?int?age;}

定義Client和GET請求接口public?interface?Client?{

@GET("users")

Call>??getUsers();}

這段代碼定義了一個接口Client, 并定義了一個GET函數getUsers(), 該函數用戶向服務器發送get請求獲取所有的 用戶信息. 定義GET請求需要用GET注解來修飾函數, 注解的參數為uri的相對路徑, 下一部分會定義URL的地址, 在 發送GET請求時, retrofit會將GET的參數和服務器拼接. 后面會在該接口中實現其他的POST和GET函數.

注:?在retrofit2.0中,要注意GET和POST注解的參數,如果參數以"/"開頭,那么在跟base地址拼接時,會將base地址中 的相對地址全部覆蓋掉. 舉例: base地址為"http://a/b", GET參數為"/c/d", 那么最后的請求地址為"http://a/c/d", 因此,如果base地址本身已經是相對地址, 那么GET/POST的參數不能以"/"開頭.

public?class?MainActivity?{

....

public?static?final?String?SERVER_URL?=?"http://10.10.10.10/account";

private?OkHttpClient?okHttpClient?=?new?OkHttpClient();

private?Retrofit.Builder?builder?=?new?Retrofit.Builder()

.base_url(SERVER_URL)

.client(okHttpClient)

.addConvertFactory(GsonConvertFactory.create());

Retrofit?retrofit?=?builder.build();

Client?client?=?retrofit.create(Client.class);

Call>?call?=?client.getUsers();

List?result?=?call.execute().body();

....}

上述代碼用來做實際的請求動作, 首先通過Retrofit Builder來基于各種參數(服務器地址, httpclient, converter) 生成一個builder對象, 讓后調用builder的build()函數生成一個retrofit對象.

接著,調用retrofit的create()函數,傳入上一步中定義的接口作為參數來實例化一個具體的接口對象, 然后調用 該對象的具體http請求函數(這里為getUsers())來實現http請求. 請求的結果是Json數據,會通過GsonConverter轉化為具體的 對象(即User). 由于是多個對象,所以需要放到一個List中.

上述三步即為retrofit的基本使用方法.

創建一個Service generator類

如果項目中?針對同一個server地址?需要創建多個Retrofit Interface service,那么可以創建一個通用的ServiceGenerator類 來生成service實例.public?class?ServiceGenerator?{

public?static?final?String?BASE_URL?=?"";

private?static?OkHttpClient?httpClient?=?new?OkHttpClient();

private?static?Retrofit.Builder?builder?=

new?Retrofit.Builder()

.baseUrl(BASE_URL)

.addConverterFactory(GsonConverterFactory.create());

public?static??T?createService(Class?serviceClass){

//把設置client放到這里是因為后續有對client進行配置的需求

Retrofit?retrofit?=?builder.client(httpClient).build();

return?retrofit.create(serviceClass);

}

}

這樣在上一節的MainActivity中,可以直接使用ServiceGenerator來創建Client實例Client?client?=?ServiceGenerator.create(Client.class);Client?call?=?client.getUsers();List?result?=?call.execute().body();

帳號密碼認證的ServiceGenerator類

帳號密碼是一種常見的認證方式, 通常將其加密后以放入到http頭部的Authorization中 進行請求認證.通過對OkHttpClient進行配置可以在retrofit中實現該方式.public?static??T?createService(Class?serviceClass){

createService(serviceClass,?null,?null);}pubic?static??T?createService(Class?serviceCls,?String?userName,?String?passWord)??{

if?(userName?!=?null?&&?passWord?!=?null)?{

//對用戶名和密碼進行加密(不同的需求加密方式不一樣,?這里只提供參考)

String?credentials?=?userName?+?":"?+?passWord;

final?String?base64Str?=?Base64.encodeToString(credentials.getBytes(),?Base64.NO_WRAP);

httpClient.interceptors().clear();

httpClient.interceptors().add(new?Interceptor()?{

@Override

public?Response?intercept(Interceptor.Chain?chain)?throws?IOException?{

Request?original?=?chain.request();

Request.Builder?requestBuilder?=?original.newBuilder()

.header("Authorization",?basic);

.header("Accept",?"applicaton/json");

.method(original.method(),?original.body());

Request?request?=?requestBuilder.build();

return?chain.proceed(request);

}

});

}

Retrofit?retrofit?=?builder.client(httpClient).build();

return?retrofit.create(serverClass);}

上述代碼通過修改OkHttpClient的相關參數來修改API請求的頭部, 講加密后的帳號和密碼放入到 Authorization中實現驗證.

注: Interceptors是屬于OkHttp的相關內容, 這部分在后面學習OkHttp時會介紹.

OAuth認證接口的ServiceGenerator類

整合過第三方API的同學肯定對OAuth接口不陌生, 大部分情況下你都需要去第三方開發者 平臺注冊你的app去獲取一個id和secret, 這樣才可以訪問第三方的接口.

注: 關于oauth的介紹可以參考阮一峰老師的文章?理解OAuth2.0.

基于前面的代碼, 重新寫一個OAuth相關的createService()函數.public?static??T?createService(Class?serviceClass,?AccessToken?token)?{

if?(token?!=?null)?{

httpClient.interceptors().clear();

httpClient.interceptors().add(new?Interceptor()?{

@Override

public?Response?intercept(Interceptor.Chain?chain)?throws?IOException?{

Request?original?=?chain.request();

Request.Builder?builder2?=?original.newBuilder()

.header("Accept",?"application/json")

.header("Authorization",?token.getTokenType()+?"?"?+?token.getAccessToken())

.method(original.method(),?original.body());

Request?request?=?builder2.build();

return?chain.proceed(request);

}

});

Retrofit?retrofit?=?builder.client(httpClient).build();

return?retrofit.create(serverClass);

}}

上面的代碼通過創建一個定制的?RequestInterceptor?對象來配置httpClient, 在定制的對象中將token信息 添加到Http表頭的Authorization域. 不過一般情況下, Access Token并不是直接可以從服務器獲取的, 下面就會講解一下獲取Access Token的常用方法.

場景: 假設你已經在第三方網站注冊了你的app, 獲取了一個clientId 和 secret, 你使用這個帳號來想注冊服務器獲取 授權碼(一般是跳轉到一個網頁, 點擊允許操作), 然后再通過授權碼獲取Access Token, 下面是主要流程.獲取授權碼 授權碼的獲取一般需要跳轉到第三方api的一個相關的網頁,網頁中會詢問用戶是否允許用戶 app獲取其在該網站的信息.如果用戶點擊允許, 第三方服務器就會生成一個授權碼返回給用戶. 第一步先創建程序主界面:public?class?LoginActivity?extends?Activity?{

//在第三方平臺注冊應用獲取的clientId和secret

private?final?String?clientId?=?"your-client-id";

private?final?String?clientSecret?=?"your-client-secret";

//獲取跳轉碼后的跳轉url,?在申請授權碼時需要一并傳給第三方服務器

private?final?String?redirectUri?=?"your://redirecturi";

@Override

protected?void?onCreate(Bundle?savedInstanceState)?{

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_login);

Button?loginButton?(Button)?findViewById(R.id.loginbutton);

loginButton.setOnClickListener(new?View.OnClickListener()?{

@Override

public?void?onClick(View?v)?{

Intent?intent?=?new?Intent(

Intent.ACTION_VIEW,

Uri.parse(ServiceGenerator.API_BASE_URL?+?"/login"?+?"?client_id="?+?clientId?+?"&redirect_uri="?+?redirectUri));

startActivity(intent);

}

});

}}

上述代碼定義了一個基本的Android界面, 界面只有一個按鈕, 點擊按鈕會請求授權碼(一般會跳轉到一個授權界面). 在請求中傳入一個了回調地址, 如果用戶授權一般第三方服務器帶著授權碼會跳到這個地址, 所以必須在請求授權碼 時傳入回調地址. 這在Android中會表現發送回調Uri的廣播,并將授權碼通過intent傳遞出去. 所以app中需要在注冊一個可以接受該intent的界面,這里還是使用主界面. 在AndroidMainfest.xml中設置intent-filter #+BEGIN_SRC xml

#+END_EXAMPLE

在onResume處理接受到的Intent. 這里假設授權碼在intent中傳遞并且key值為code(第三方平臺的回調方式需要參考他們的文檔).@Overrideprotected?void?onResume()?{

super.onResume();

Uri?uri?=?getIntent().getData();

if?(uri?!=?null?&&?uri.toString().startsWith(redirectUri))?{

String?code?=?uri.getQueryParameter("code");

if?(code?!=?null)?{

//處理授權碼

}?else?if?(uri.getQueryParameter("error")?!=?null)?{

//處理錯誤

}

}}

好, 到此為止,我們就已經獲取到了授權碼,下一步就是通過授權碼獲取Access Token.獲取Access Token 上一步獲取到授權碼后, 就可以向第三方的Access Token服務器發送請求獲取token. 我們可以寫一個retrofit服務 來實現這個功能.public?interface?LoginService?{

@POST("/token")

Call?getAccessToken(

@Query("code")?String?code,

@Query("grant_type")?String?grantType);}

這里的code就是上一步獲取的授權碼, grantType是授權類型. 然后用下面的代碼加入到onResume獲取成功的代碼段中if?(code?!=?null)?{

//?get?access?token

LoginService?loginService?=

ServiceGenerator.createService(LoginService.class,?clientId,?clientSecret);

Call?call?=?loginService.getAccessToken(code,?"authorization_code");

AccessToken?accessToken?=?call.execute().body();}

以上都是示例, 代碼具體寫法請參考相關第三方文檔.

同步請求 vs 異步請求

Retrofit支持同步和異步請求, 不過Retrofit2的同步/異步架構功能與1有 很大不同, 具體請參考相關文檔.同步請求 直接調用execute()函數, 本文中的實例就是同步請求的例子.

注意事項:不要在Android的主線程中調用execute(),有可能報錯或導致ANR.

異步請求 異步請求的話調用enque()函數, 并向enque()傳入一個Callback的參數. 并需要要實現Callback的onSuccess和onFailure函數.

請求結果Response類

當調用execute()或enqueue()函數時, 會返回一個Reponse對象表示請求結果. 該請求結果包含了以下信息:結果碼: 調用code()函數獲得

結果對象: 調用body()函數獲得, 如示例所示.

頭部: 調用headers

原始返回結果: 調用rawResponse()函數, 返回一個OkHttp的Response對象.

Tips請求失敗, body()返回值為null

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/396008.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/396008.shtml
英文地址,請注明出處:http://en.pswp.cn/news/396008.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

層次聚類算法 算法_聚類算法簡介

層次聚類算法 算法Take a look at the image below. It’s a collection of bugs and creepy-crawlies of different shapes and sizes. Take a moment to categorize them by similarity into a number of groups.看看下面的圖片。 它是各種形狀和大小的錯誤和令人毛骨悚然的爬…

.h .dll .lib

.h為對一個函數的聲明引用,include就是聲明某個文件里的函數(內只有聲明函數被引用了),編譯時使用 .lib為鏈接時用的,存放的是對于DLL里函數的位置信息等,這樣不必把所有dll里函數都加載到內存里&#xff0…

《機器人學經典教程》——2.2 控制論

本節書摘來異步社區《機器人學經典教程》一書中的第2章,第2.2節,作者:【美】Maja J. Matari?(馬婭?馬塔里奇),更多章節內容可以訪問云棲社區“異步社區”公眾號查看。 2.2 控制論 隨著控制理論的不斷發展…

嗶哩嗶哩網站前端源碼_分享一個仿制嗶哩嗶哩鏡子網站源碼

我老婆非常喜歡看嗶哩嗶哩,前些天她興奮地和我說嗶哩嗶哩網站有個隱藏的彩蛋,傳送門http://www.ilidilid.com/,我看了下,相當于把鏡子中的網站樣子弄出來了。于是,我尋思著,把自己的博客也弄個這樣的彩蛋&a…

promise-async-await

通常而言,這3個關鍵字 都是用來「優雅」的處理ajax異步請求的 //es6的時候promise誕生,很好的解決了嵌套回調地獄,改良方案為鏈式回調。// es2017的時候誕生了async、await,這下異步直接沒有回調了,像同步一樣爽//沒有…

第一沖刺階段博客檢查

我們檢查的團隊是:紅鳥 ①團隊博客: 該團隊將所有的站立會議均寫到了4月28日的一篇博客中,并且其中任務看板和燃盡圖不全。 ②團隊成員個人博客: 1>張曉晨: 沒有每天個人工作總結。 2>王曉思: 從4.19…

netcore 編譯 html,Asp.Net Core中的@ Html.Action

小編典典更新:從2.2.2版本開始,HttpContextAccessor將上下文保留在一個對象中(據說是為了防止請求之間的混淆),這會影響當前解決方案…因此,您需要為IHttpContextAccessor(舊版本)提供以下實現并進行注冊作為一個單例:…

《CCIE路由和交換認證考試指南(第5版) (第1卷)》——1.6節虛擬交換系統

本節書摘來自異步社區《CCIE路由和交換認證考試指南(第5版) (第1卷)》一書中的第1章,第1.6節虛擬交換系統,作者 【美】Narbik Kocharians(那比克 科查理安) , 【斯洛伐克】Peter Pal…

機器學習 美股_我如何使用機器學習來探索英美文學之間的差異

機器學習 美股by Sofia Godovykh索非亞戈多維克(Sofia Godovykh) 我如何使用機器學習來探索英美文學之間的差異 (How I used machine learning to explore the differences between British and American literature) As I delved further into English literature to further…

遠程執行漏洞修復方案_請馬上修復!SaltStack遠程命令執行漏洞

【漏洞預警】SaltStack遠程命令執行漏洞(CVE-2020-11651、CVE-2020-11652)2020年5月3日,阿里云應急響應中心監測到近日國外某安全團隊披露了SaltStack存在認證繞過致命令執行漏洞以及目錄遍歷漏洞。漏洞描述SaltStack是基于Python開發的一套C/S架構配置管理工具。國…

kafka部分重要參數配置-broker端參數

broker端參數主要在config/server.properties目錄下設置: 啟動命令:nohup ./kafka-server-start.sh -daemon ../config/server.properties & broker.id參數:Kafka使用唯一的一個整數來標識每個broker,全局唯一,默認…

JS正則表達式大全(整理詳細且實用)

JS正則表達式大全(整理詳細且實用) 作者: 字體:[增加 減小] 類型:轉載 時間:2013-11-14 我要評論 JS正則表達式大全(整理詳細且實用)。需要的朋友可以過來參考下,希望對大家有所幫助正則表達式中的特殊字符 字符 含意…

html設置模塊寬度為200像素,css 寬度(CSS width)

DIV CSS寬度width樣式屬性CSS 寬度是指通過CSS 樣式設置對應div寬度,以下我們了解傳統html寬度、寬度自適應百分比、固定寬度等寬度知識。傳統Html 寬度屬性單詞:width 如width"300";CSS 寬度屬性單詞:width 如width:300px;一、Wid…

我從Stack Overflow對64,000名開發人員的大規模調查中學到的東西

Today Stack Overflow released the results of their 2017 survey of more than 64,000 developers.今天,Stack Overflow發布了他們對64,000多名開發人員的2017年調查結果。 Just like in 2016, I’ve combed through these results and summarized them for you.…

《Node應用程序構建——使用MongoDB和Backbone》一第 1 章 介紹與總覽1.1 打造一個社交網絡...

本節書摘來自異步社區《Node應用程序構建——使用MongoDB和Backbone》一書中的第1章,第1.1節,作者【美】Mike Wilson,更多章節內容可以訪問云棲社區“異步社區”公眾號查看 第 1 章 介紹與總覽 Node應用程序構建——使用MongoDB和Backbone互…

jquery 樣式獲取設置值_jQuery獲取樣式中的背景顏色屬性值/顏色值

天使用jQuery獲取樣式中的background-color的值時發現在獲取到的顏色值在IE中與Chrome、Firefox顯示的格式不一樣,IE中是以HEX格式顯示#ffff00,而Chrome、Firefox中則是以GRB格式顯示rgb(255,0,0),由于需要將顏色值存儲到數據庫中&#xff0c…

計算機專業做產品,非計算機專業如何做產品經理?

《硅谷產品實戰》學習筆記 32課這節課中講了計算機專業背景對產品經理的幫助:第一印象;判斷項目復雜度;了解技術可否實現,有何限制?對于沒有計算機專業背景的產品如何彌補專業不足?關于如何判斷項目復雜度在…

_UICreateCGImageFromIOSurface 使用API

上傳的時候,蘋果發送郵件 Non-public API usage: The app references non-public symbols in DUO-LINK 4: _UICreateCGImageFromIOSurfaceIf method names in your source code match the private Apple APIs listed above, altering your method names will help …

匹配一個字符串的開頭和結尾_我如何構建一個應用程序來展示精彩小說的開頭和結尾

匹配一個字符串的開頭和結尾I know sentences. In my decade as a print journalist, I’ve written hundreds of articles for dozens of publications. I’ve dished out more sentences than Judge Judy. But I didn’t study writing or journalism, at least not formally…

python 社區網絡轉化_python-將numpy打開網格轉換為坐標

方法1使用np.meshgrid,然后堆疊-r,c np.meshgrid(*m)out np.column_stack((r.ravel(F), c.ravel(F) ))方法2或者,使用np.array()然后進行轉置,重塑-np.array(np.meshgrid(*m)).T.reshape(-1,len(m))對于np.ix_中使用的通用數組數目的通用情況,這里是需要進行的修改-p np.r_[…