在行動應用程式開發中,許多操作(如網路請求、資料庫查詢或大型計算)需要較長的時間才能完成。如果將這些操作放在主執行緒中執行,可能會導致應用程式的介面卡頓或無法回應使用者操作。為了避免這種情況,我們通常會將這些耗時的任務移到背景執行緒中執行,並使用非同步操作來確保主執行緒能夠保持響應。本章將探討執行緒的概念、如何使用 Service 來管理背景工作,以及如何處理非同步操作與回呼。
執行緒(Thread)是程式執行的基本單位,每個程式至少有一個主執行緒負責管理 UI 和使用者互動。然而,當你執行一個耗時操作時,如果不使用額外的執行緒,應用程式的主執行緒會被阻塞,導致 UI 失去響應。因此,我們可以通過創建新的執行緒來執行這些耗時操作,確保應用程式的流暢性。
Sub Process_Globals
Dim t As Thread
End Sub
Sub Globals
End Sub
Sub Activity_Create(FirstTime As Boolean)
t.Initialize("t")
t.Run(Null, "LongRunningTask", Null)
End Sub
Sub LongRunningTask
' 模擬一個耗時操作
Sleep(3000)
Log("Task completed in background thread.")
End Sub
這段程式碼展示了如何在背景執行緒中運行一個耗時操作,並避免阻塞主執行緒。
Service 是一種在背景中執行的特殊模組,適合用於需要長時間運行的任務,如下載、播放音樂或定期執行的任務。Service 具有以下特點:
• 獨立於 UI:Service 在背景執行,不依賴於應用程式的活動狀態,即使使用者關閉了 UI,Service 仍然可以繼續運行。
• 靈活的啟動方式:Service 可以通過多種方式啟動,如時間觸發、事件觸發等。
• 低記憶體佔用:Service 一般比活動(Activity)佔用更少的記憶體,適合長時間運行。
' 在Service模組中
Sub Service_Create
' 初始化
End Sub
Sub Service_Start (StartingIntent As Intent)
' 背景任務
StartServiceAt("", DateTime.Now + 10 * DateTime.TicksPerSecond, True)
Log("Service is running.")
End Sub
Sub Service_Destroy
' Service 結束時清理資源
Log("Service destroyed.")
End Sub
你可以通過以下方式從 Activity 中啟動這個 Service:
Sub StartMyService
StartService(MyService)
End Sub
這段程式碼會啟動 MyService 並讓它在背景中運行指定的任務。
2. 定期執行的Service
如果你的應用程式需要定期執行某些任務,可以使用 StartServiceAt 方法來設定一個定期執行的 Service。例如,每隔 10 秒執行一次某個任務:
Sub Service_Start (StartingIntent As Intent)
' 設定每10秒執行一次
StartServiceAt("", DateTime.Now + 10 * DateTime.TicksPerSecond, True)
Log("Service running every 10 seconds.")
End Sub
這段程式碼會在 Service 啟動後,每隔 10 秒再次執行 Service_Start 中的代碼。
非同步操作是指那些不會阻塞主執行緒的操作,這些操作通常會在背景執行,完成後透過回呼(Callback)將結果返回給主執行緒。這樣的設計能夠確保應用程式在處理長時間任務時,依然保持 UI 的流暢和響應。
Sub DownloadFile
Dim job As HttpJob
job.Initialize("Job1", Me)
job.Download("https://www.example.com/file.txt")
End Sub
Sub JobDone (Job As HttpJob)
If Job.Success Then
Log("Download completed: " & Job.GetString)
Else
Log("Error: " & Job.ErrorMessage)
End If
Job.Release
End Sub
這段程式碼使用 HttpJob 在背景中下載一個檔案,下載完成後透過 JobDone 回呼函數處理結果。
2. 使用非同步操作優化UI體驗
非同步操作的使用不僅能提高應用程式的響應速度,還能優化整體的使用者體驗。例如,在執行一個長時間的網路請求時,可以在主執行緒中顯示一個載入指示器,當背景任務完成後再隱藏該指示器。
Sub ExecuteLongRunningTask
ProgressDialogShow("Loading...")
Dim job As HttpJob
job.Initialize("LongTask", Me)
job.Download("https://api.example.com/data")
End Sub
Sub JobDone (Job As HttpJob)
ProgressDialogHide
If Job.Success Then
Log("Data received: " & Job.GetString)
Else
Log("Error: " & Job.ErrorMessage)
End If
Job.Release
End Sub
這樣設計可以確保在網路請求的過程中,使用者不會感覺應用程式卡頓,並能清楚地看到請求的進度。
以下是一個綜合範例,展示了如何使用背景執行緒、Service 和非同步操作來處理一個複雜的任務。
Sub Process_Globals
' 全域變數
Dim t As Thread
End Sub
Sub Globals
Dim btnStartTask As Button
End Sub
Sub Activity_Create(FirstTime As Boolean)
Activity.LoadLayout("MainLayout")
btnStartTask.Initialize("btnStartTask")
btnStartTask.Text = "Start Background Task"
Activity.AddView(btnStartTask, 50, 50, 200, 50)
End Sub
Sub btnStartTask_Click
' 啟動背景執行緒處理耗時操作
t.Initialize("t")
t.Run(Null, "BackgroundTask", Null)
End Sub
Sub BackgroundTask
Log("Background task started.")
Sleep(5000)
Log("Background task completed.")
' 通知主執行緒任務完成
CallSub(Main, "OnTaskComplete")
End Sub
Sub OnTaskComplete
ToastMessageShow("Background task completed.", False)
End Sub
這個範例展示了如何在背景執行緒中執行一個長時間任務,並在任務完成後通知主執行緒更新 UI。這種設計確保了應用程式的 UI 在執行耗時操作時仍能保持響應。
通過合理使用背景執行緒和非同步操作,你可以開發出更加高效、流暢的行動應用程式,提供良好的使用者體驗。
參考網址
https://www.b4x.com/teach.html
https://www.b4x.com/learn.html