(一)理論基礎
? LiveData
?和?ViewModel
?是 Android 架構組件中的重要部分,它們在構建響應式、生命周期感知的 Android 應用程序中發揮著關鍵作用。下面分別介紹它們的原理。
LiveData 原理
1. 概述
LiveData
?是一種可觀察的數據持有者類,它具有生命周期感知能力,這意味著它能遵循其他應用組件(如?Activity
、Fragment
)的生命周期。只有處于活躍狀態(如?STARTED
?或?RESUMED
)的觀察者才能收到數據更新的通知。
2. 核心組成部分
LiveData
?類:作為數據的持有者,它內部維護了一個數據對象和一個觀察者列表。Observer
?接口:定義了一個?onChanged(T t)
?方法,當?LiveData
?中的數據發生變化時,會調用該方法通知觀察者。LifecycleOwner
?接口:表示具有生命周期的對象,如?Activity
?和?Fragment
?都實現了該接口。LiveData
?通過?Lifecycle
?來感知?LifecycleOwner
?的生命周期狀態。
3. 工作原理
- 注冊觀察者:當調用?
LiveData.observe(LifecycleOwner owner, Observer<? super T> observer)
?方法時,LiveData
?會將?LifecycleOwner
?和?Observer
?包裝成一個?LifecycleBoundObserver
?對象,并將其添加到觀察者列表中。同時,LifecycleBoundObserver
?會監聽?LifecycleOwner
?的生命周期變化。
// Java 示例
LiveData<String> liveData = new MutableLiveData<>();
observe(lifecycleOwner, new Observer<String>() {@Overridepublic void onChanged(String s) {// 處理數據變化}
});
- 生命周期感知:
LifecycleBoundObserver
?實現了?LifecycleEventObserver
?接口,當?LifecycleOwner
?的生命周期狀態發生變化時,LifecycleBoundObserver
?會收到相應的事件通知。如果?LifecycleOwner
?進入活躍狀態(STARTED
?或?RESUMED
),LiveData
?會將最新的數據發送給該觀察者;如果?LifecycleOwner
?進入銷毀狀態(DESTROYED
),LiveData
?會自動移除該觀察者,以避免內存泄漏。 - 數據更新:當調用?
LiveData.setValue(T value)
?或?LiveData.postValue(T value)
?方法更新數據時,LiveData
?會檢查所有觀察者的生命周期狀態,只有處于活躍狀態的觀察者才會收到?onChanged
?方法的調用。
ViewModel 原理
1. 概述
ViewModel
?旨在存儲和管理與 UI 相關的數據,并且在配置更改(如屏幕旋轉)時保持數據的一致性。它的生命周期比?Activity
?或?Fragment
?更長,直到關聯的?Activity
?或?Fragment
?被銷毀(對于?Activity
?是?onDestroy()
?調用且不是由于配置更改;對于?Fragment
?是?onDestroy()
?調用)。
2. 核心組成部分
ViewModel
?類:開發者自定義的?ViewModel
?類需要繼承自?ViewModel
?類,用于存儲和管理與 UI 相關的數據。ViewModelProvider
?類:負責創建和管理?ViewModel
?實例。它使用?ViewModelStore
?來存儲?ViewModel
?實例。ViewModelStore
?類:是一個簡單的鍵值對存儲結構,用于存儲?ViewModel
?實例。每個?Activity
?和?Fragment
?都有一個對應的?ViewModelStore
。
3. 工作原理
- 創建?
ViewModel
?實例:當調用?ViewModelProvider(owner).get(MyViewModel.class)
?方法時,ViewModelProvider
?會首先檢查?ViewModelStore
?中是否已經存在指定類型的?ViewModel
?實例。如果存在,則直接返回該實例;如果不存在,則使用?ViewModelProvider.Factory
?創建一個新的?ViewModel
?實例,并將其存儲在?ViewModelStore
?中。
// Java 示例
ViewModelProvider viewModelProvider = new ViewModelProvider(this);
MyViewModel viewModel = viewModelProvider.get(MyViewModel.class);
- 配置更改時數據保留:當發生配置更改(如屏幕旋轉)時,
Activity
?或?Fragment
?會被銷毀并重新創建,但?ViewModelStore
?會被保留。因此,重新創建的?Activity
?或?Fragment
?可以從?ViewModelStore
?中獲取之前的?ViewModel
?實例,從而保持數據的一致性。 - 生命周期管理:當?
Activity
?或?Fragment
?被銷毀(不是由于配置更改)時,ViewModelStore
?會調用?clear()
?方法,該方法會遍歷所有存儲的?ViewModel
?實例,并調用它們的?onCleared()
?方法,以便進行資源釋放。
? LiveData
?是具有生命周期感知能力的數據持有者,通過監聽?LifecycleOwner
?狀態更新活躍觀察者,ViewModel
?借助?ViewModelProvider
?和?ViewModelStore
?存儲管理 UI 數據,在配置更改時保留數據并在關聯組件非配置更改銷毀時清理資源。
? ?下一階段? ?
? Room 是 Android 官方提供的一個 SQLite 對象映射庫,用于在 Android 應用中簡化數據庫操作,WorkManager 是 Android 架構組件之一,用于在應用中調度和管理后臺任務。
Room 工作原理?
- 抽象層封裝:Room 提供了一個抽象層,將 SQLite 數據庫的操作抽象成 Java 或 Kotlin 接口和注解。開發者可以通過定義實體類(
@Entity
)、數據訪問對象(@Dao
)和數據庫類(@Database
)來描述數據庫結構和操作。 - 編譯時處理:在編譯時,Room 會根據開發者定義的注解生成相應的 SQLite 語句和實現代碼。這樣可以在編譯時發現數據庫操作中的錯誤,提高開發效率和代碼的健壯性。
- 線程管理:Room 默認不允許在主線程中執行數據庫操作,因為數據庫操作通常是耗時的,可能會導致 UI 卡頓。因此,Room 會將數據庫操作放在后臺線程中執行。
定義實體類:
import androidx.room.Entity
import androidx.room.PrimaryKey@Entity(tableName = "users")
data class User(@PrimaryKey(autoGenerate = true)val id: Int = 0,val name: String,val age: Int
)
定義數據訪問對象(DAO):
import androidx.room.Dao
import androidx.room.Insert@Dao
interface UserDao {@Insertsuspend fun insertUser(user: User)
}
定義數據庫類:
import androidx.room.Database
import androidx.room.RoomDatabase@Database(entities = [User::class], version = 1)
abstract class AppDatabase : RoomDatabase() {abstract fun userDao(): UserDao
}
WorkManager 工作原理
- 任務調度:WorkManager 會根據任務的約束條件(如網絡連接、電池狀態等)和設備的當前狀態來決定何時執行任務。它會盡量在設備處于空閑狀態時執行任務,以減少對用戶體驗的影響。
- 任務持久化:WorkManager 會將任務信息持久化到本地數據庫中,即使應用被殺死或設備重啟,任務信息也不會丟失。當設備滿足任務的約束條件時,WorkManager 會重新調度任務執行。
- 生命周期管理:WorkManager 會自動處理任務的生命周期,包括任務的執行、重試和取消等操作。它會根據任務的狀態(如運行中、已完成、失敗等)更新任務信息。
創建 WorkManager 任務
import android.content.Context
import androidx.work.Worker
import androidx.work.WorkerParameters
import kotlinx.coroutines.runBlockingclass InsertUserWorker(context: Context, params: WorkerParameters) : Worker(context, params) {override fun doWork(): Result {val database = Room.databaseBuilder(applicationContext,AppDatabase::class.java,"app-database").build()val userDao = database.userDao()val user = User(name = "John", age = 30)runBlocking {userDao.insertUser(user)}return Result.success()}
}
調度 WorkManager 任務?
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import androidx.work.OneTimeWorkRequest
import androidx.work.WorkManagerclass MainActivity : AppCompatActivity() {override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)setContentView(R.layout.activity_main)val workRequest = OneTimeWorkRequest.Builder(InsertUserWorker::class.java).build()WorkManager.getInstance(this).enqueue(workRequest)}
}
Room + WorkManager 協同工作原理
- 數據交互:WorkManager 可以在后臺任務中執行 Room 數據庫操作,如插入、查詢、更新和刪除數據。這樣可以避免在主線程中執行耗時的數據庫操作,提高應用的性能和響應速度。
- 任務調度:當應用需要在特定條件下執行數據庫操作時,可以使用 WorkManager 來調度這些任務。例如,當設備連接到網絡時,執行數據同步任務,將本地數據庫中的數據上傳到服務器。
- 數據一致性:由于 WorkManager 會保證任務的執行,即使應用在任務執行過程中被殺死或設備重啟,任務也會在合適的時機繼續執行。這樣可以確保數據庫操作的完整性和數據的一致性。
?總結:
? Room 作為 Android 的 SQLite 對象映射庫,在編譯時根據注解生成數據庫操作代碼并管理線程,WorkManager 依據任務約束和設備狀態調度持久化的后臺任務,二者結合時 WorkManager 可在后臺任務里執行 Room 的數據庫操作,保障數據一致性,實現時先添加依賴,再定義 Room 數據庫,創建 WorkManager 任務,最后調度任務執行。
? 下一篇我將講述面試中我被項目拷打到的點!!!
感謝觀看!!!