APP開發實戰8-API介面設計
3.1介面設計注意事項
(1)首先需要確定APP和伺服器間用什麼格式傳輸資料,常用的有兩種:XML和JSON。如下使用XML格式和JSON格式表示同樣的資料,進行比較:
<?xmlversion="1.0" encoding="utf-8" ?>
<country>
<name>中國</name>
<province>
<name>廣東</name>
<citys>
<city>廣州</city>
<city>深圳</city>
</citys>
</province>
<province>
<name>廣西</name>
<citys>
<city>南寧</city>
<city>桂林</city>
</citys>
</province>
</country>
(以上是XML格式的資料)
{
"name":"中國",
"quantity": 2,
"provinces": [
{
"name": "廣東",
"quantity": 2,
"citys": {
"city": [
"廣州",
"深圳"
]
}
},
{
"name": "廣西",
"quantity": 2,
"citys": {
"city": [
"南寧",
"桂林"
]
}
}
]
}
(以上是JSON格式的資料)
從上述示例可看出,XML檔案中存在大量的描述資訊,會大大增加網路傳輸資料;同樣的內容,用JSON格式,傳輸的資料比較少,相應的網路傳輸速度和資料解析速度都快,所以首選JSON格式。
JSON格式的欄位型別值常用的有以下幾種:
Number:整數或浮點數
String:字串
Boolean:true 或 false
上述三種屬於基本型別
Array:陣列,包含在方括號[]中
Object:物件,包含在大括號{}中
上述二種屬於複合型別,其中可以包含各類基本型別欄位
示例如下:
{//物件
"name":"中國", //字串
"quantity": 2,//整數
"isAsia": true,//布林型別
"provinces": [//陣列
{
"name": "廣東",
"quantity": 2,
"citys": {
"city": [
"廣州",
"深圳"
]
}
},
{
"name": "廣西",
"quantity": 2,
"citys": {
"city": [
"南寧",
"桂林"
]
}
}
]
}
(2)需要設計JSON資料的具體格式:
傳送請求(有非陣列格式的具體引數),如:
{
"params":{
"username":"aaa",
"password":"123456"
}
}
傳送請求(有陣列格式的具體引數),如:
{
"params": {
"products": [
{
"name": "可樂",
"quantity ": 1
},
{
"name": "雪碧",
"quantity ": 2
}
]
}
}
傳送請求(無具體引數),如:
{
"params": {
}
}
操作成功(只返回操作狀態,不返回資料),如:
{
"code": 800
}
操作成功(返回操作狀態和非陣列資料),如:
{
"code": 800
"result":{
"message":"訂單提交成功"
}
}
操作成功(返回操作狀態和陣列資料) ,如:
{
"code": 800
"result":{
"products": [
{
"name": "可樂",
"quantity ": 1
},
{
"name": "雪碧",
"quantity ": 2
}
]
}
}
操作失敗(只返回操作狀態和出錯提示) ,如:
{
"code": 801
"result":{
"message":"密碼錯誤,請重新輸入"
}
}
在定義JSON中的欄位名稱時,儘量短小,以減少網路傳輸資料量。
(3)伺服器端採用的語言即有Java這樣的強型別語言,也有PHP這樣的弱型別語言,弱型別語言對變數型別沒有強型別語言那麼嚴格,但Android和iOS開發使用的語言都是強型別的,導致APP端常會遇到變數型別出錯的問題,如需要整型資料,結果伺服器傳的數字有小數,及需要非字串型別的資料,結果伺服器傳的資料是字串等。
為解決這類問題,在和伺服器端定義欄位的資料型別時,建議使用以下方案:
A在APP端涉及到數學的加、減、乘、除或比較大小運算的欄位,統一使用double型別;int和float型別可以算是double型別的子集,這樣只要APP端使用double型別,無論伺服器端返回是int型別,還是float型別,都不會解析出錯。
B布林型的欄位也使用double型別代替,伺服器端返回1表示true,返回0表示false。
C不涉及數學的加、減、乘、除或比較大小運算的欄位,且非布林型的欄位,統一使用字串型別。字串型別的適應性比較強,無論哪種型別的資料,都可以當字串處理,解析的時候不容易出錯。
這樣APP和伺服器端互動,只使用了兩種基本資料型別,大大減少了由於各種資料型別不相容導致APP端資料解析出錯的問題。
(4)APP端從伺服器讀取資料的時候,會遇到資料為空的情況,此時伺服器端返回給APP的資料型別應該和資料不為空時的型別一致。
如下所示:
{
"code": 800
"result":{
"nikeName":""
}
}
nikeName欄位的型別是字串,當其值為空時,應返回空字串"",而不應返回null。
{
"code": 800
"result":{
"products":[]
}
}
products欄位的型別是陣列,當其值為空時,應返回空陣列[],而不應返回null或其它型別的資料。
(5)因為伺服器端的介面程式碼可能會發生變化,所以在APP端向伺服器端傳送請求時,最好把介面的版本號也帶上,如下所示:
{
"version":1.0,
"params":{
"username":"aaa",
"password":"123456"
}
}
以上JSON資料中,version欄位的值表示當前使用介面的版本號為1.0。
如已經上線的舊APP中使用的介面版本是1.0,在上線後接口更新到1.1版本,而且不相容1.0版本,使用者有可能不更新APP,還是使用舊版本APP。
伺服器端接收到請求後,發現APP使用的介面版本是1.0,就可以呼叫舊介面處理APP請求;如果請求中不帶版本號,遇到這種狀況,就很難處理了。
(6)APP往往需要從伺服器獲取圖片,但伺服器的圖片往往不完全適合APP需要,就需要先在伺服器端按APP的需要處理圖片,然後把處理過的圖片傳給APP;APP在傳送獲取圖片的請求時,把所需圖片的寬度和高度發給伺服器,如採用GET命令,可以按以下方式:
http://www.hello.com/getimage/2/width/100/hight/100
伺服器收到請求,就可先按APP要求的尺寸處理圖片,再發給APP。
當然也可以用POST命令實現,用JSON格式傳遞引數,如下:
{
"version":1.0,
"params":{
"imageId":2,
"width":100,
"hight":100
}
}
(7)大多數APP和伺服器互動時用HTTP協議,每向伺服器傳送一個請求都要先建立連線,傳輸資料,然後再斷開連線;即使伺服器端有做連線池設計,但連線池中容納的連線個數有限制。
在設計介面時,在APP端執行的每一個動作,儘量做到只需向伺服器傳送一次請求;也要減少APP在進入一個新介面時,傳送請求的次數,以減少APP和伺服器建立連線和斷開連線消耗的時間及資源,提高程式響應速度。
(8)對於向APP返回陣列資料的介面應設計支援分頁操作,提供引數供APP端設定獲取元素的起始位置和獲取的個數:
陣列中有100個元素,但APP端可能第一次從第1個元素開始只讀取10個元素,第二次從第11各元素開始只讀取5個元素。
如電商APP中讀取商品列表和訂單列表等就需要這樣設計。
如讀取商品列表的JSON資料:
{
"version":1.0,
"params":{
"categoryId":1,
"offset":0,
"limit":10
}
}
其中categoryId表示讀取哪一類別的商品列表,offset表示從商品列表中的第一個商品開始讀取商品資料,limit表示讀取10個商品資料。limit的數值也可以在伺服器端配置,此時以伺服器端的數值為準,APP傳遞的數值不起作用。
(9)對於可能會變動的功能邏輯,都放在伺服器端實現,而不是APP本地實現,這樣後續的功能變更時,修改伺服器端的程式碼就可以了,不需要使用者升級APP。如電商APP中商品的排序功能,在伺服器端把商品排序後,再把資料傳遞給APP,APP端只負責顯示就可以了。
(10)APP端在使用伺服器介面的時候,遇到的最多問題就是從伺服器傳來的JSON資料型別和約定的不一致,導致APP端解析出錯,APP遇到此類問題,往往會Crash,需要對此問題做特別處理,如下所示:
try {
// parseJson為解析從伺服器返回的JSON資料的函式
T model = parseJson(jsonData);
onSuccess(model);
}catch(Exception e){
message= "資料解析出錯";
onError(message);
}
開發Android APP時,利用try…catch…機制,可以有效防止APP Crash,並提示使用者出現了什麼問題。
在開發階段,APP端應明確提示:資料解析出錯,這樣有利於發現和解決問題。
如果上線後,使用者使用APP的時候遇到這類問題,提示:資料解析出錯,使用者不一定理解具體含義,可換種方式提示,如下:
如上圖所示,明確告知使用者,伺服器端出現問題了,需要聯絡客服解決。
開發階段通常使用debug版本,而線上版本是release版本,可以利用編譯選項實現不同版本顯示不同的提示資訊。