Android Retrofit 教學 (Java 篇)

常見的 HTTP 網路資料請求連線套件

名稱參考資料
HttpURLConnectionhttps://developer.android.com/reference/java/net/HttpURLConnection
Volleyhttps://developer.android.com/training/volley
OKHttphttps://square.github.io/okhttp/
Retrofithttps://square.github.io/retrofit/

Retrofit 跟其他連線套件比較,省去很多繁瑣的設定,速度更快,使用上方便,擴充也容易是目前業界廣納採用的連線套件。

Retrofit 官方介紹與使用教學

https://square.github.io/retrofit/

添加 Retrofit 依賴庫 (dependencies)

在 GRADLE (Module) 層級 dependencies 內加入:

implementation 'com.squareup.retrofit2:retrofit:2.7.2'

若想將資料轉成 Gson,可以加入:

implementation 'com.squareup.retrofit2:converter-gson:2.7.2'

Retrofit 還提供很多資料格式轉換,詳細可參考官方介紹:

若想使用最新版本可以到 mvnrepository 查看最新版號:

權限宣告 (permissions)

連線網路,需在 AndroidManifest.xml 中宣告:

<uses-permission android:name="android.permission.INTERNET" />

JSONPlaceholder 假資料網站

這一次範例我們將使用 JSONPlaceholder 所提供的假資料 RESTful API 來做串接練習。

JSONPlaceholder 提供六種常用資源,如:貼文、照片、用戶…等假資料、。

還有 GET、POST、PUT、PATCH、DELETE 等 HTTP 請求方法可以使用。

其中可以透過呼叫 https://jsonplaceholder.typicode.com/posts/1 可以得到回應格式為 json 的資料。

{
  "userId": 1,
  "id": 1,
  "title": "sunt aut facere repellat provident occaecati excepturi optio reprehenderit",
  "body": "quia et suscipit\nsuscipit recusandae consequuntur expedita et cum\nreprehenderit molestiae ut ut quas totam\nnostrum rerum est autem sunt rem eveniet architecto"
}

Post 資料類別

根據上面的 json 回應資料,我們可以設計出我們的 Post.java 資料類別為:

public class Post {
    private int id;
    private String title;
    private String body;
    private int userId;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public String getBody() {
        return body;
    }

    public void setBody(String body) {
        this.body = body;
    }

    public int getUserId() {
        return userId;
    }

    public void setUserId(int userId) {
        this.userId = userId;
    }
}

Ps.資料類別,老司機通常會在 Android Studio 裝 plugins 套件: Json2Class ,只要將 json 輸出資料貼上,即可快速幫你轉出資料別。

當然也可以透過手動宣告資料欄位與名稱,再按右鍵快速產出 getter and setter。

這邊要注意的是資料類別中的欄位名稱一定要跟 json 輸出資料名稱一致,若不相同,抓的資料將會是 null。資料欄位一多,出錯機率就容易高,KT 這邊會建議資料類別就交由外掛套件來產生,減少事後名稱校正半天。

interface

Retrofit 使用前,需先定義一個 interface,以此例,我們自定義一個叫 getPost 方法,當我們呼叫此方法,將會用 HTTP 中的「GET」方法,到 /post 位置,取回資料,然後包裝轉換成我們定義的 Post 資料類別回傳給呼叫的點。

public interface FakeAPIService {
    @GET("/posts/1") //annotation 註解宣告方式定義 HTTP 連線獲取資料方法與指定API後網址
    Call<Post> getPost();
}
  • @GET:就是指用 HTTP 中的 GET 方法。以此類推,若要使用 POST 或是 DELETE 只要將此處改你要的 HTTP 方法。

  • API 完整網址是「 https://jsonplaceholder.typicode.com/posts 」,我們將他拆成兩個部分,前綴為共用的網域名稱的部分「https://jsonplaceholder.typicode.com」給提出,剩下後綴為「/posts」

  • getPost 是我們自定義的方法名稱,等一下呼叫這個方法,Retrofit 將會根據你定義 annotation 的 HTTP 方法,到你指定API 位置取回資料。

Retrofit 使用方式

有我們剛剛定義的 Post 資料類別和 FakeAPIService 的介面後,即可以來使用 Retrofit 連線功能。

// baseUrl: 定義 API 網域網址,即是我們剛剛拆出來的前綴共用的部分
// ddConverterFactory: 定義要將資料轉成什麼格式
Retrofit retrofit = new Retrofit.Builder()
        .baseUrl("https://jsonplaceholder.typicode.com")
        .addConverterFactory(GsonConverterFactory.create())
        .build();

FakeAPIService fakeAPIService = retrofit.create(FakeAPIService.class);

//宣告 Call 連線服務
Call<Post> call = fakeAPIService.getPost();

//執行連線服務,透過 Callback 來等待回傳成功或失敗的資料
call.enqueue(new Callback<Post>() {
    @Override
    public void onResponse(Call<Post> call, Response<Post> response) {
     // 連線成功,透過 getter 取得特定欄位資料
        Log.d("HKT", "id: " + response.body().getId());
        Log.d("HKT", "title: " + response.body().getTitle());
        Log.d("HKT", "body: " + response.body().getBody());
        Log.d("HKT", "userId: " + response.body().getUserId());
    }

    @Override
    public void onFailure(Call call, Throwable t) {
      // 連線失敗,印出錯誤訊息
        Log.d("HKT", "response: " + t.toString());
    }
});

多筆資料接收方式

呼叫 https://jsonplaceholder.typicode.com/posts 可以得到多筆資料。

[
  {
    "userId": 1,
    "id": 1,
    "title": "sunt aut facere repellat provident occaecati excepturi optio reprehenderit",
    "body": "quia et suscipit\nsuscipit recusandae consequuntur expedita et cum\nreprehenderit molestiae ut ut quas totam\nnostrum rerum est autem sunt rem eveniet architecto"
  },
  ...
  ...
  ...
]

在 FakeAPIService 介面中,新增加入要透過 get 方法訪問 /posts,透過 List 資料格式來承接多筆資料。

public interface FakeAPIService {
    //取得單筆資料()
    @GET("/posts/1")
    Call<Post> getPost();

    //取得多筆資料
    @GET("/posts")
    Call<List<Post>> getPosts();
}

原 <Post> 只能收一筆資料,要收多筆資料需改成 <List<Post>>即可:

...
...
...

Call<List<Post>> call = fakeAPIService.getPosts();
call.enqueue(new Callback<List<Post>>() {
    @Override
    public void onResponse(Call<List<Post>> call, Response<List<Post>> response) {
        // 透過 foreach 取出每一筆資料內容
        for (Post item : response.body()
        ) {
            Log.d("HKT", "id: " + item.getId());
            Log.d("HKT", "title: " + item.getTitle());
            Log.d("HKT", "body: " + item.getBody());
            Log.d("HKT", "userId: " + item.getUserId());
        }
    }

    @Override
    public void onFailure(Call call, Throwable t) {
        Log.d("HKT", "response: " + t.toString());
    }
});

常見錯誤

Q1

Invoke-customs are only supported starting with android 0 --min-api 26

Static interface methods are only supported starting with Android N (--min-api 24): okhttp3.Request okhttp3.Authenticator.lambda$static$0(okhttp3.Route, okhttp3.Response)

Error: Invoke-customs are only supported starting with Android O (--min-api 26)

若發生以上類似錯誤,請在 GRADLE (Module) 層級 Android 內加入:

android {
    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }
}

Q2

Trying to parse JSON data from URL : Unable to resolve host “jsonplaceholder.typicode.com”: No address associated with hostname

若發生以上類似錯誤,有可能你忘記在 AndroidManifest 宣告,使用網路權限,另外一個就是你的網路不通。

贊助我們

創作不易,知識無價,免費線上教學就像顆種子,希望藉由您的支持與贊助,能夠無後顧之憂的日漸茁壯,努力前行堅持下去。不論捐贈金額的大小,我們都由衷的感謝每位贊助者,都是我們推廣知識、開放共享知識最大的動力!

您的捐贈將用於:請作者喝杯咖啡,鼓勵繼續創作,持續上傳教學影片與更多新技術文章。

Line Pay 打賞


(由 Line Pay 支付平台,提供一卡通轉帳服務)

街口打賞


(由街口行動支付平台,提供轉帳服務)

超商代碼繳費打賞

(由綠界科技支付平台,提供超商繳費代碼)


相關連結

HKT 線上教室 每週六日 更新影片
▶ YouTube 頻道
https://goo.gl/3f2pJi
▶ KT 線上教室 臉書粉絲團
https://goo.gl/27H9Li
▶ Udemy 頻道
http://bit.ly/2ZNdnrt
▶ 贊助我們
https://goo.gl/FiKXAu

從零開始學 Dart 程式設計 線上影片教學(完整版)
🎬 http://bit.ly/32toHt3

Flutter 程式設計入門實戰 30 天 線上影片教學(完整版)
🎬 http://bit.ly/2t1SjBu

從零開始學 Java 程式設計 線上影片教學(完整版)
🎬 http://bit.ly/376wXCx

從零開始學 kotlin 程式設計 線上影片教學(完整版)
🎬 http://bit.ly/2ODUanq

APP / Dart / Flutter / Android Studio
Android / iOS / Java / Kotlin / 教學 / 開發

這個網誌中的熱門文章

16天記下7000單字

2023 最新入門零基礎 Kotlin教學【從零開始學 Kotlin 程式設計】Kotlin 教學課程目錄 (Android Kotlin, IntelliJ IDEA, Android Studio, Android APP 開發教學)

nano 文字編輯器

Android Studio 歷代版本下載點

最新入門零基礎 Java 教學【從零開始學 Java 程式設計】Java教學課程目錄 (IntelliJ IDEA 開發教學)