iT邦幫忙

2025 iThome 鐵人賽

DAY 25
0

在第二十四天,你已經成功讓你的 App 擁有了「網路連線」的能力,可以從網路上獲取資料了!

但你可能也發現,用 HttpURLConnection 進行網路連線,需要寫很多程式碼(例如:建立 Thread、讀取 InputStream、處理 Handler)。如果我們每次要連線都要重複寫這些程式碼,會非常麻煩。

這時,我們就需要一個更專業、更自動化的「網路電話」,也就是今天的重點:Retrofit

什麼是 Retrofit

  • 簡單比喻: Retrofit 就像是 App 的 「智慧型網路電話」
    • 你只需要告訴它,你想要連到哪個網站、想要取得什麼資料。
    • 它就會自動幫你處理所有繁瑣的細節,像是建立連線、在背景執行、讀取資料、甚至是將資料轉換成你需要的格式。
  • 主要特性:
    • 簡單易用:你只需要用幾個介面 (Interface) 和註解 (Annotation),就能定義好所有的網路請求。
    • 自動化Retrofit 會自動處理網路連線、錯誤處理、資料轉換等工作。
    • 非同步:它內建了非同步處理機制,讓你的 App 不會因為等待網路連線而卡住。

實作時間:用 Retrofit 改造你的查詢 App

今天,我們要用 Retrofit 來改造昨天的專案,讓 App 依然去同一個網站取得資料,但程式碼會變得更簡潔。

1. 在你的專案中新增 Retrofit 函式庫

  • 開啟 build.gradle (Module: app) 檔案。
  • dependencies 區塊中,加入以下幾行程式碼:
`dependencies {
    // ... 其他 dependencies ...

    // Retrofit 函式庫
    implementation 'com.squareup.retrofit2:retrofit:2.9.0'
    // 將 JSON 轉換成 Java 物件的函式庫 (與 Retrofit 搭配使用)
    implementation 'com.squareup.retrofit2:converter-gson:2.9.0'
}`

然後點擊右上角的 Sync Now

2. 建立一個 API 介面 (Interface)

  • 簡單比喻: 這就是你的「電話簿」,你只需要在這裡定義好所有的「電話號碼」(也就是網路請求的 URL 和方法)。
  • 右鍵點擊 MainActivity.java 所在的資料夾,選擇 New -> Java Class -> Interface
  • 類別名稱取為 ApiService
`import retrofit2.Call;
import retrofit2.http.GET;

public interface ApiService {
    // 定義一個 GET 請求,用來取得文章
    // @GET 註解告訴 Retrofit,這是一個 GET 請求
    // "posts/1" 是相對於網址的「電話號碼」
    @GET("posts/1")
    Call<Post> getPost(); // Call 是 Retrofit 的回傳型別,<Post> 是我們要接收的資料型別
}`

3. 建立一個資料類別 (Data Class)

  • 簡單比喻: 這就是你的「收件箱」,用來定義你想要接收的資料格式。
  • 網站回傳的 JSON 資料,通常會包含 userId, id, title, body 這幾個欄位。我們需要建立一個對應的 Java 類別來接收。
  • 建立一個新的 Java 類別,取名為 Post
`import com.google.gson.annotations.SerializedName;

public class Post {
    @SerializedName("userId")
    private int userId;

    @SerializedName("id")
    private int id;

    @SerializedName("title")
    private String title;

    @SerializedName("body")
    private String body;

    // 這裡可以加上 getter 方法,方便我們取得資料
    public String getTitle() {
        return title;
    }
}`

4. 修改你的 MainActivity.java

這是最後一步。我們只需要用 Retrofit 建立一個實例,然後呼叫我們定義好的方法即可!

`import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;

import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;

public class MainActivity extends AppCompatActivity {

    private TextView resultTextView;
    private Button fetchButton;

    // 網站的「總機」號碼
    private static final String BASE_URL = "https://jsonplaceholder.typicode.com/";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        resultTextView = findViewById(R.id.resultTextView);
        fetchButton = findViewById(R.id.fetchButton);

        fetchButton.setOnClickListener(v -> fetchDataWithRetrofit());
    }

    private void fetchDataWithRetrofit() {
        // 1. 建立 Retrofit 實例
        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl(BASE_URL) // 你的網站總機號碼
                .addConverterFactory(GsonConverterFactory.create()) // 啟用 JSON 資料轉換
                .build();

        // 2. 建立 ApiService 介面實例
        ApiService apiService = retrofit.create(ApiService.class);

        // 3. 呼叫你的「電話號碼」 (getPost 方法)
        Call<Post> call = apiService.getPost();

        // 4. 非同步執行請求
        call.enqueue(new Callback<Post>() {
            @Override
            public void onResponse(Call<Post> call, Response<Post> response) {
                if (response.isSuccessful() && response.body() != null) {
                    // 請求成功!自動將 JSON 轉換成 Post 物件
                    Post post = response.body();
                    resultTextView.setText(post.getTitle()); // 取得 title 並顯示
                    Toast.makeText(MainActivity.this, "資料獲取成功!", Toast.LENGTH_SHORT).show();
                } else {
                    resultTextView.setText("資料獲取失敗!");
                }
            }

            @Override
            public void onFailure(Call<Post> call, Throwable t) {
                // 網路連線失敗
                resultTextView.setText("網路連線失敗!");
                t.printStackTrace();
            }
        });
    }
}`
  • 程式碼解釋:
    • Retrofit.Builder():用來建立 Retrofit 實例,你只需要設定好網站的「總機號碼」(baseUrl)。
    • create(ApiService.class):這會自動幫你創建 ApiService 介面的實例。
    • call.enqueue(...):這就是非同步請求的關鍵。Retrofit 會自動在背景執行請求,並在成功 (onResponse) 或失敗 (onFailure) 時回傳結果。

執行你的 App!

  • 點擊綠色的「」按鈕,執行 App。
  • 點擊「從網路獲取資料」按鈕。
  • 你會看到 TextView 中顯示出從網路上取得的 title 文字!

今日總結

今天我們學會了:

  • Retrofit 的概念,以及它比 HttpURLConnection 的優勢。
  • 如何使用 RetrofitGson 來處理網路連線和資料轉換。
  • 成功用更簡潔、更專業的程式碼,實現了網路連線的功能。

你已經掌握了 App 開發最核心的幾大技能!接下來的幾天,我們將會進入綜合實作,將所有學過的知識串聯起來,完成一個更完整的 App 專案。

明天見!


上一篇
Day24- App 的多工處理:執行緒與 Handler
系列文
Android 開發者養成計畫:從程式邏輯到作品集實戰25
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言