iT邦幫忙

2025 iThome 鐵人賽

DAY 24
0
Mobile Development

Android 開發者養成計畫:從程式邏輯到作品集實戰系列 第 24

Day24- App 的多工處理:執行緒與 Handler

  • 分享至 

  • xImage
  •  

在第二十三天,你已經成功地讓 App 擁有了「網路連線」的能力。這代表你的 App 不再是一個單機程式,而是可以與全世界互動了!

但在開發過程中,你可能會聽到一個重要的觀念:「不要在主執行緒上執行耗時任務!」 這是什麼意思呢?

這時,我們就需要一個 App 的「多工處理」能力,也就是今天的重點:執行緒

什麼是執行緒 (Thread)?

  • 簡單比喻:執行緒就像是 App 的 「工作線」
    • 一個 App 預設只有一條「主工作線」(主執行緒,Main Thread)。它專門負責處理畫面顯示、使用者輸入等「前台」工作。
    • 當你開啟一個新的「工作線」(子執行緒,Background Thread)時,它就能在後台執行耗時的任務,而不會影響到主工作線。
  • 主要概念
    • 主執行緒 (Main Thread):又稱 UI 執行緒,負責處理所有與使用者介面相關的工作。如果你在這裡執行耗時任務,App 會卡住,甚至出現「應用程式沒有回應」(ANR)的錯誤。
    • 子執行緒 (Background Thread):負責處理所有耗時的、與 UI 無關的工作,例如網路請求、檔案讀取、資料庫操作等。

Handler:主執行緒與子執行緒的橋樑

  • 簡單比喻Handler 就像是 「主工作線的聯絡員」
    • 子執行緒不能直接對 UI 進行操作(例如修改 TextView 的文字)。
    • 當子執行緒完成工作後,它會請 Handler 這個「聯絡員」去向主執行緒發送一個訊息,並由主執行緒來更新 UI。

Thread vs. Coroutines:現代與傳統

在 Java 中,我們通常會用 Thread 來執行多工任務,但在 Android 開發的演進中,出現了一個更現代、更輕量的解決方案:Kotlin Coroutines

  • Thread:你可以想像它是一個 「實體的工人」。雇用一個實體的工人成本很高(佔用更多記憶體),而且管理多個工人會讓老闆的工作變得更複雜。
  • Coroutines:你可以想像它是一個 「虛擬的分身」。它不是一個實體的工人,而是由 App 內部管理的、非常輕量的「分身」。它的優點是資源消耗極低,開發上更簡潔。

雖然你的鐵人賽系列是以 Java 為主,但了解 Coroutines 的概念能讓你的知識體系更完整,並為你未來學習 Kotlin 打下基礎。

實作時間:用 Thread 與 Handler 解決耗時任務

今天,我們要製作一個 App:點擊按鈕後,App 會進行一個模擬的「長時間運算」,並在運算完成後,將結果顯示在畫面上。

1. 修改你的 activity_main.xml

我們需要一個 Button 和一個 TextView

`<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="center"
    android:orientation="vertical"
    android:padding="16dp">

    <Button
        android:id="@+id/startButton"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="開始運算" />

    <TextView
        android:id="@+id/resultTextView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="32dp"
        android:text="運算結果"
        android:textSize="20sp" />

</LinearLayout>`

2. 修改你的 MainActivity.java

這是最關鍵的部分。我們要在 Button 的點擊事件中,啟動一個新的執行緒來執行模擬的耗時任務。

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

public class MainActivity extends AppCompatActivity {

    private Button startButton;
    private TextView resultTextView;
    // 這是主執行緒的聯絡員
    private Handler mainHandler = new Handler(Looper.getMainLooper());

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

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

        startButton.setOnClickListener(v -> {
            // 在點擊按鈕時,啟動一個新的執行緒
            new Thread(new Runnable() {
                @Override
                public void run() {
                    performLongTask();
                }
            }).start();
        });
    }

    private void performLongTask() {
        // 模擬一個耗時 3 秒的運算
        try {
            Thread.sleep(3000); // 讓這個執行緒「睡覺」3 秒
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        final String result = "運算完成!";

        // 透過 Handler 將結果傳回給主執行緒,並更新 UI
        mainHandler.post(() -> {
            resultTextView.setText(result);
            Toast.makeText(MainActivity.this, "任務完成!", Toast.LENGTH_SHORT).show();
        });
    }
}`

執行你的 App!

  • 點擊綠色的「」按鈕,執行 App。
  • 你會發現 App 畫面不會卡住,3 秒後,TextView 會自動顯示「運算完成!」

今日總結

今天我們學會了:

  • 主執行緒子執行緒 的概念。
  • 為什麼耗時任務不能在主執行緒上執行。
  • 如何使用 Thread 創建一個子執行緒。
  • 如何使用 Handler 將結果從子執行緒傳回給主執行緒,並安全地更新 UI。

明天將會介紹一個更專業、更強大的網路連線函式庫:Retrofit。它能讓你的網路連線程式碼變得更簡潔、更優雅,是目前業界最主流的工具之一。

明天見!


上一篇
Day23- 讓 App 連結全世界:網路連線 (HttpURLConnection)
下一篇
Day25- Retrofit 函式庫
系列文
Android 開發者養成計畫:從程式邏輯到作品集實戰25
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言