1. 程式人生 > >APP開發實戰8-API介面設計

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版本,可以利用編譯選項實現不同版本顯示不同的提示資訊。