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 開發教學)

2022 最新入門零基礎 Flutter教學 【Flutter 程式設計入門實戰 30 天】Flutter 教學課程目錄 (IntelliJ IDEA 開發教學)

nano 文字編輯器

【從零開始學 Flutter 程式設計】SharedPreferences 設定檔資料存取