亚洲中字慕日产2020,大陆极品少妇内射AAAAAA,无码av大香线蕉伊人久久,久久精品国产亚洲av麻豆网站

資訊專欄INFORMATION COLUMN

[譯] WorkManager 基礎(chǔ)入門

番茄西紅柿 / 1598人閱讀

摘要:讓我們探討一下如何確保你的工作脫離主線程運(yùn)行并保證執(zhí)行。這確保在默認(rèn)情況下,你的工作是同步運(yùn)行的,并且在主線程之外運(yùn)行。這是應(yīng)該脫離主線程運(yùn)行的工作,但是,因?yàn)樗c直接相關(guān),所以如果關(guān)閉應(yīng)用程序則不需要繼續(xù)。


原文地址:WorkManager Basics

原文作者:Lyla Fujiwara

譯文出自:掘金翻譯計(jì)劃

本文永久鏈接:github.com/xitu/gold-m…

譯者:Rickon

校對(duì)者:Feximin

插圖來(lái)自 Virginia Poltrack

歡迎來(lái)到我們 WorkManager 系列的第二篇文章。WorkManager 是一個(gè) Android Jetpack 庫(kù),當(dāng)滿足工作的約束條件時(shí),用來(lái)運(yùn)行可延遲、需要保障的后臺(tái)工作。對(duì)于許多類型的后臺(tái)工作,WorkManager 是當(dāng)前的最佳實(shí)踐方案。在第一篇博文中,我們討論了 WorkManager 是什么以及何時(shí)使用 WorkManager。

在這篇博文中,我將介紹:

將你的后臺(tái)任務(wù)定義為工作

定義特定的工作應(yīng)該如何運(yùn)行

運(yùn)行你的工作

使用鏈進(jìn)行存在依賴的工作

監(jiān)視你的工作的狀態(tài)

我還將解釋 WorkManager 幕后發(fā)生的事情,以便你可以就如何使用它做出明智的決定。

從一個(gè)例子開(kāi)始

假設(shè)你有一個(gè)圖片編輯應(yīng)用,可讓你給圖像加上濾鏡并將其上傳到網(wǎng)絡(luò)讓全世界看到。你希望創(chuàng)建一系列后臺(tái)任務(wù),這些任務(wù)用于濾鏡,壓縮圖像和之后的上傳。在每個(gè)環(huán)節(jié),都有一個(gè)需要檢查的約束——給圖像加濾鏡時(shí)要有足夠的電量,壓縮圖像時(shí)要有足夠的存儲(chǔ)空間,以及上傳圖像時(shí)要有網(wǎng)絡(luò)連接。

這個(gè)例子如上圖所示

這個(gè)例子正是具有以下特點(diǎn)的任務(wù):

可延遲的,因?yàn)槟悴恍枰⒓磮?zhí)行,而且實(shí)際上可能希望等待某些約束被滿足(例如等待網(wǎng)絡(luò)連接)。

需要確保能夠運(yùn)行,無(wú)論應(yīng)用程序是否退出,因?yàn)槿绻恿藶V鏡后的圖像永遠(yuǎn)沒(méi)能與世界共享,你的用戶會(huì)非常不滿意!

這些特點(diǎn)使我們的圖像加濾鏡和上傳任務(wù)成為 WorkManager 的完美用例。

添加 WorkManager 依賴

本文使用 Kotlin 書寫代碼,使用 KTX 庫(kù)(KoTlin eXtensions)。KTX 版本的庫(kù)提供了 擴(kuò)展函數(shù) 為了更簡(jiǎn)潔和習(xí)慣的使用 Kotlin。你可以添加如下依賴來(lái)使用 KTX 版本的 WorkManager:

dependencies {
 def work_version = "1.0.0-beta02"
 implementation "android.arch.work:work-runtime-ktx:$work_version"
}

你可以在 這里](developer.android.com/topic/libra…) 到該庫(kù)的最新版本。如果你想使用 Java 依賴,那就移除“-ktx”。

定義你的 work 做什么

在我們將多個(gè)任務(wù)連接在一起之前,讓我們關(guān)注如何執(zhí)行一項(xiàng)工作。我將會(huì)著重細(xì)說(shuō)上傳任務(wù)。首先,你需要?jiǎng)?chuàng)建自己的 Worker 實(shí)現(xiàn)類。我將會(huì)把我們的類命名為 UploadWorker,然后重寫 doWork() 方法。

Workers:

定義你的工作實(shí)際做了什么。

接受輸入并產(chǎn)生輸出。輸入和輸出都以鍵值對(duì)表示。

始終返回表示成功,失敗或重試的值。

這是一個(gè)示例,展示了如何實(shí)現(xiàn)上傳圖像的 Worker

class UploadWorker(appContext: Context, workerParams: WorkerParameters)
    : Worker(appContext, workerParams) {

    override fun doWork(): Result {
        try {
            // Get the input
            val imageUriInput = inputData.getString(Constants.KEY_IMAGE_URI)

            // Do the work
            val response = upload(imageUriInput)

            // Create the output of the work
            val imageResponse = response.body()
            val imgLink = imageResponse.data.link
            // workDataOf (part of KTX) converts a list of pairs to a [Data] object.
            val outputData = workDataOf(Constants.KEY_IMAGE_URI to imgLink)

            return Result.success(outputData)

        } catch (e: Exception) {
            return Result.failure()
        }
    }

    fun upload(imageUri: String): Response {
        TODO(“Webservice request code here”)
        // Webservice request code here; note this would need to be run
        // synchronously for reasons explained below.
    }

}

有兩點(diǎn)需要注意:

輸入和輸出是作為 Data 傳遞,它本質(zhì)上是原始類型和數(shù)組的映射。Data 對(duì)象應(yīng)該相當(dāng)小 —— 實(shí)際上可以輸入/輸出的總大小有限制。這由 MAX_DATA_BYTES 設(shè)置。如果您需要將更多數(shù)據(jù)傳入和傳出 Worker,則應(yīng)將數(shù)據(jù)放在其他地方,例如 Room database。作為一個(gè)例子,我傳入上面圖像的 URI,而不是圖像本身。

在代碼中,我展示了兩個(gè)返回示例:Result.success()Result.failure()。還有一個(gè) Result.retry() 選項(xiàng),它將在之后的時(shí)間再次重試你的工作。

定義您的 work 應(yīng)該如何運(yùn)行

一方面 Worker 定義工作的作用,另一方面 WorkRequest 定義應(yīng)該如何以及何時(shí)運(yùn)行工作

以下是為 UploadWorker 創(chuàng)建 OneTimeWorkRequest 的示例。也可以有重復(fù)性的 PeriodicWorkRequest

// workDataOf (part of KTX) converts a list of pairs to a [Data] object.
val imageData = workDataOf(Constants.KEY_IMAGE_URI to imageUriString)

val uploadWorkRequest = OneTimeWorkRequestBuilder()
        .setInputData(imageData)
        .build()

WorkRequest 將輸入 imageData: Data 對(duì)象,并盡快運(yùn)行。

假設(shè) UploadWork 并不總是應(yīng)該立即運(yùn)行 —— 它應(yīng)該只在設(shè)備有網(wǎng)絡(luò)連接時(shí)運(yùn)行。你可以通過(guò)添加 Constraints 對(duì)象來(lái)完成此操作。你可以創(chuàng)建這樣的約束:

val constraints = Constraints.Builder()
        .setRequiredNetworkType(NetworkType.CONNECTED)
        .build()

以下是其他受支持約束的示例:

val constraints = Constraints.Builder()
        .setRequiresBatteryNotLow(true)
        .setRequiredNetworkType(NetworkType.CONNECTED)
        .setRequiresCharging(true)
        .setRequiresStorageNotLow(true)
        .setRequiresDeviceIdle(true)
        .build()

最后,還記得 Result.retry() 嗎?我之前說(shuō)過(guò),如果 Worker 返回 Result.retry(),WorkManager 將重新計(jì)劃工作。你可以在創(chuàng)建新的 WorkRequest 時(shí)自定義退避條件。這允許你定義何時(shí)應(yīng)重試運(yùn)行。

退避條件由兩個(gè)屬性定義:

BackoffPolicy,默認(rèn)為指數(shù)性的,但是可以設(shè)置為線性。

持續(xù)時(shí)間,默認(rèn)為 30 秒。

用于對(duì)上傳工作進(jìn)行排隊(duì)的組合代碼如下,包括約束,輸入和自定義退避策略:

// Create the Constraints
val constraints = Constraints.Builder()
        .setRequiredNetworkType(NetworkType.CONNECTED)
        .build()

// Define the input
val imageData = workDataOf(Constants.KEY_IMAGE_URI to imageUriString)

// Bring it all together by creating the WorkRequest; this also sets the back off criteria
val uploadWorkRequest = OneTimeWorkRequestBuilder()
        .setInputData(imageData)
        .setConstraints(constraints)        
        .setBackoffCriteria(
                BackoffPolicy.LINEAR, 
                OneTimeWorkRequest.MIN_BACKOFF_MILLIS, 
                TimeUnit.MILLISECONDS)
        .build()
運(yùn)行 work

這些都很好,但你還沒(méi)有真正調(diào)度好你的工作去運(yùn)行。以下是告訴 WorkManager 調(diào)度工作所需的一行代碼:

WorkManager.getInstance().enqueue(uploadWorkRequest)

你首先需要獲取 WorkManager 的實(shí)例,這是一個(gè)負(fù)責(zé)執(zhí)行你的工作的單例。調(diào)用 enqueue 來(lái)啟動(dòng) WorkManager 跟蹤和調(diào)度工作的整個(gè)過(guò)程。

在幕后 —— 工作是怎么運(yùn)行的

那么,WorkManager 能為您做些什么呢?默認(rèn)情況下,WorkManager 會(huì):

脫離主線程運(yùn)行你的工作(假設(shè)你正在繼承 Worker 類,如上面的 UploadWorker 所示)。

保障 你的工作將會(huì)運(yùn)行(即使你重啟設(shè)備或應(yīng)用程序退出,它也不會(huì)忘記運(yùn)行你的工作)。

根據(jù)用戶 API 級(jí)別的最佳實(shí)踐運(yùn)行(如上一篇文章所述)。

讓我們探討一下 WorkManager 如何確保你的工作脫離主線程運(yùn)行并保證執(zhí)行。在幕后,WorkManager 包括以下部分:

內(nèi)部 TaskExecutor:一個(gè)單線程 Executor,處理所有排隊(duì)工作的請(qǐng)求。如果您不熟悉 Executors,可以在這里閱讀更多相關(guān)信息。

WorkManager 數(shù)據(jù)庫(kù):一個(gè)本地?cái)?shù)據(jù)庫(kù),可跟蹤所有工作的所有信息和狀態(tài)。這包括工作的當(dāng)前狀態(tài),工作的輸入和輸出以及對(duì)工作的任何約束限制。此數(shù)據(jù)庫(kù)使 WorkManager 能夠保證你的工作能夠完成 —— 如果你的用戶的設(shè)備重新啟動(dòng)并且工作中斷,則可以從數(shù)據(jù)庫(kù)中提取工作的所有詳細(xì)信息,并在設(shè)備再次啟動(dòng)時(shí)重新啟動(dòng)工作。

WorkerFactory:一個(gè)默認(rèn)工廠,用于創(chuàng)建 Worker 的實(shí)例。我們將在以后的博文中介紹為什么以及如何配置它。

Default Executor:一個(gè)默認(rèn)的執(zhí)行程序,運(yùn)行你的工作,除非你另行指定。這確保在默認(rèn)情況下,你的工作是同步運(yùn)行的,并且在主線程之外運(yùn)行。

這些部分可以被重寫以具有不同的行為。

來(lái)自:Working with WorkManager Android 開(kāi)發(fā)者大會(huì)展示 2018

當(dāng)你安排 WorkRequest

    內(nèi)部 TaskExecutor 立即將你的 WorkRequest 信息保存到 WorkManager 數(shù)據(jù)庫(kù)。

    稍后,當(dāng)滿足 WorkRequestConstraints 時(shí)(可以立即發(fā)生),Internal TaskExecutor 會(huì)告訴 WorkerFactory 創(chuàng)建一個(gè) Worker。

    之后,默認(rèn)的 Executor 調(diào)用你的 WorkerdoWork() 方法脫離主線程。

通過(guò)這種方式,默認(rèn)情況下,你的工作都可以保證執(zhí)行脫離主線程運(yùn)行。

現(xiàn)在,如果你想使用除默認(rèn) Executor 之外的一些其他機(jī)制來(lái)運(yùn)行你的工作,也是可以的!對(duì)協(xié)程(CoroutineWorker)和 RxJava(RxWorker)的開(kāi)箱即用支持作為工作的手段。

或者,你可以使用 ListenableWorker 準(zhǔn)確指定工作的執(zhí)行方式。Worker 實(shí)際上是 ListenableWorker 的一個(gè)實(shí)現(xiàn),它默認(rèn)在默認(rèn)的 Executor 上運(yùn)行你的工作,因此是同步的。所以,如果你想要完全控制工作的線程策略或異步運(yùn)行工作,你可以將 ListenableWorker 子類化(具體細(xì)節(jié)將在后面的文章中討論)。

WorkManager 雖然將所有工作信息保存到數(shù)據(jù)庫(kù)中有些麻煩,但它還是會(huì)做,這使得它成了非常適合需要保障執(zhí)行的任務(wù)。這也是使得 WorkManager 輕松應(yīng)對(duì)對(duì)于不需要保障且只需要在后臺(tái)線程上執(zhí)行的任務(wù)的的原因。例如,假設(shè)你已經(jīng)下載了圖像,并且希望根據(jù)該圖像更改 UI 部分的顏色。這是應(yīng)該脫離主線程運(yùn)行的工作,但是,因?yàn)樗c UI 直接相關(guān),所以如果關(guān)閉應(yīng)用程序則不需要繼續(xù)。所以在這樣的情況下,不要使用 WorkManager —— 堅(jiān)持使用像 Kotlin 協(xié)程那樣輕量的東西或創(chuàng)建自己的 Executor

使用鏈進(jìn)行依賴性工作

我們的濾鏡示例包含的不僅僅是一個(gè)任務(wù) —— 我們想要給多個(gè)圖像加濾鏡,然后壓縮并上傳。如果要一個(gè)接一個(gè)地或并行地運(yùn)行一系列 WorkRequests,則可以使用 鏈。示例圖顯示了一個(gè)鏈,其中有三個(gè)并行運(yùn)行的濾鏡任務(wù),后面是壓縮任務(wù)和上傳任務(wù),按順序運(yùn)行:

使用 WorkManager 非常簡(jiǎn)單。假設(shè)你已經(jīng)用適當(dāng)?shù)募s束創(chuàng)建了所有 WorkRequests,代碼如下所示:

WorkManager.getInstance()
    .beginWith(Arrays.asList(
                             filterImageOneWorkRequest, 
                             filterImageTwoWorkRequest, 
                             filterImageThreeWorkRequest))
    .then(compressWorkRequest)
    .then(uploadWorkRequest)
    .enqueue()

三個(gè)圖片濾鏡 WorkRequests 并行執(zhí)行。一旦完成所有濾鏡 WorkRequests (并且只有完成所有三個(gè)),就會(huì)發(fā)生 compressWorkRequest,然后是 uploadWorkRequest。

鏈的另一個(gè)優(yōu)點(diǎn)是:一個(gè) WorkRequest 的輸出作為下一個(gè) WorkRequest 的輸入。因此,假設(shè)你正確設(shè)置了輸入和輸出數(shù)據(jù),就像我上面的 UploadWorker 示例所做的那樣,這些值將自動(dòng)傳遞。

為了處理并行的三個(gè)濾鏡工作請(qǐng)求的輸出,可以使用 InputMerger,特別是 ArrayCreatingInputMerger。代碼如下:

val compressWorkRequest = OneTimeWorkRequestBuilder()
        .setInputMerger(ArrayCreatingInputMerger::class.java)
        .setConstraints(constraints)
        .build()

請(qǐng)注意,InputMerger 是添加到 compressWorkRequest 中的,而不是并行的三個(gè)濾鏡請(qǐng)求中的。

假設(shè)每個(gè)濾鏡工作請(qǐng)求的輸出是映射到圖像 URI 的鍵 “KEY_IMAGE_URI”。添加 ArrayCreatingInputMerger 的作用是并行請(qǐng)求的輸出,當(dāng)這些輸出具有匹配的時(shí),它會(huì)創(chuàng)建一個(gè)包含所有輸出值的數(shù)組,映射到單個(gè)鍵??梢暬瘓D表如下:

ArrayCreatingInputMerger 功能可視化

因此,compressWorkRequest 的輸入將最終成為映射到濾鏡圖像 URI 數(shù)組的 “KEY_IMAGE_URI” 對(duì)。

觀察你的 WorkRequest 狀態(tài)

監(jiān)視工作的最簡(jiǎn)單方法是使用 LiveData 類。如果你不熟悉 LiveData,它是一個(gè)生命周期感知的可監(jiān)視數(shù)據(jù)持有者 —— 這里 對(duì)此有更詳細(xì)的描述。

調(diào)用 getWorkInfoByIdLiveData 返回一個(gè) WorkInfoLiveData。WorkInfo 包含輸出的數(shù)據(jù)和表示工作狀態(tài)的枚舉。當(dāng)工作順利完成后,它的 State 就會(huì)是 SUCCEEDED。因此,例如,你可以通過(guò)編寫一些監(jiān)視代碼來(lái)實(shí)現(xiàn)當(dāng)工作完成時(shí)自動(dòng)顯示該圖像:

// In your UI (activity, fragment, etc)
WorkManager.getInstance().getWorkInfoByIdLiveData(uploadWorkRequest.id)
        .observe(lifecycleOwner, Observer { workInfo ->
            // Check if the current works state is "successfully finished"
            if (workInfo != null && workInfo.state == WorkInfo.State.SUCCEEDED) {
                displayImage(workInfo.outputData.getString(KEY_IMAGE_URI))
            }
        })

有幾點(diǎn)需要注意:

每個(gè) WorkRequest 都有一個(gè)唯一的 id,該唯一 id 是查找關(guān)聯(lián) WorkInfo 的一種方法。

WorkInfo 更改時(shí)進(jìn)行監(jiān)視并被通知的能力是 LiveData 提供的功能。

工作有一個(gè)由不同 State 代表的生命周期。監(jiān)視 LiveData 時(shí),你會(huì)看到這些狀態(tài);例如,你可能會(huì)看到:

“happy path” 或工作狀態(tài)

工作狀態(tài)經(jīng)歷的 “happy path” 如下:

    BLOCKED:只有當(dāng)工作在鏈中并且不是鏈中的下一個(gè)工作時(shí)才會(huì)出現(xiàn)這種狀態(tài)。

    ENQUEUED:只要工作是工作鏈中的下一個(gè)并且有資格運(yùn)行,工作就會(huì)進(jìn)入這個(gè)狀態(tài)。這項(xiàng)工作可能仍在等待 Constraint 被滿足。

    RUNNING:在這種狀態(tài)時(shí),工作正在運(yùn)行。對(duì)于 Worker,這意味著 doWork() 方法已經(jīng)被調(diào)用。

    SUCCEEDED:當(dāng) doWork() 返回 Result.success() 時(shí),工作進(jìn)入這種最終狀態(tài)。

現(xiàn)在,當(dāng)工作處于 RUNNING 狀態(tài),你可以調(diào)用 Result.retry()。這將會(huì)導(dǎo)致工作退回 ENQUEUED 狀態(tài)。工作也可能隨時(shí)被 CANCELLED。

如果工作運(yùn)行的結(jié)果是 Result.failure() 而不是成功。它的狀態(tài)將會(huì)以 FAILED 結(jié)束,因此,狀態(tài)的完整流程圖如下所示:

(來(lái)自:Working with WorkManager Android 開(kāi)發(fā)者峰會(huì) 2018)

想看精彩的視頻講解,請(qǐng)查看 WorkManager Android 開(kāi)發(fā)者峰會(huì)演講。

總結(jié)

這就是 WorkManager API 的基礎(chǔ)知識(shí)。使用我們剛剛介紹的代碼片段,你現(xiàn)在就可以:

創(chuàng)建包含輸入/輸出的 Worker。

使用 WorkRequest、Constraint、啟動(dòng)輸入和退出策略配置 Worker 的運(yùn)行方式。

調(diào)度 WorkRequest。

了解默認(rèn)情況下 WorkManager 在線程和保障運(yùn)行方面的幕后工作。

創(chuàng)建復(fù)雜鏈?zhǔn)较嗷ヒ蕾嚨墓ぷ?,可以順序運(yùn)行和并行運(yùn)行。

使用 WorkInfo 監(jiān)視你的 WorkRequest 的狀態(tài)。

想親自試試 WorkManager 嗎?查看 codelab,包含 Kotlin 和 Java 代碼。

隨著我們繼續(xù)更新本系列,請(qǐng)繼續(xù)關(guān)注有關(guān) WorkManager 主題的更多博客文章。 有什么問(wèn)題或者你希望我們寫到的東西嗎?請(qǐng)?jiān)谠u(píng)論區(qū)告訴我們!

感謝 Pietro Maggi

WorkManager 相關(guān)資源

官方文檔

參考指南

WorkManager 1.0.0-beta02 Release notes

Codelab:Kotlin 和 Java.

源碼(AOSP 的一部分)

Working with WorkManager (Android 開(kāi)發(fā)者峰會(huì) 2018) presentation

Issue Tracker

StackOverflow 上面的 WorkManager 相關(guān)問(wèn)題

Google’s Power blog post series

如果發(fā)現(xiàn)譯文存在錯(cuò)誤或其他需要改進(jìn)的地方,歡迎到 掘金翻譯計(jì)劃 對(duì)譯文進(jìn)行修改并 PR,也可獲得相應(yīng)獎(jiǎng)勵(lì)積分。文章開(kāi)頭的 本文永久鏈接 即為本文在 GitHub 上的 MarkDown 鏈接。


掘金翻譯計(jì)劃 是一個(gè)翻譯優(yōu)質(zhì)互聯(lián)網(wǎng)技術(shù)文章的社區(qū),文章來(lái)源為 掘金 上的英文分享文章。內(nèi)容覆蓋 Android、iOS、前端、后端、區(qū)塊鏈、產(chǎn)品、設(shè)計(jì)、人工智能等領(lǐng)域,想要查看更多優(yōu)質(zhì)譯文請(qǐng)持續(xù)關(guān)注 掘金翻譯計(jì)劃、官方微博、知乎專欄。

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://www.ezyhdfw.cn/yun/7044.html

相關(guān)文章

  • WorkManager入門到實(shí)踐,有這一篇就夠了

    摘要:前言上一次我們對(duì)的應(yīng)用進(jìn)行了一次全面的分析,這一次我們來(lái)聊聊。 showImg(https://segmentfault.com/img/remote/1460000020077803?w=1280&h=853); 前言 上一次我們對(duì)Paging的應(yīng)用進(jìn)行了一次全面的分析,這一次我們來(lái)聊聊WorkManager。 如果你對(duì)Paging還未了解,推薦閱讀這篇文章: Paging在Recy...

    bingchen 評(píng)論0 收藏0
  • [] 在 Android 使用協(xié)程(part III) - 在實(shí)際工作中使用

    摘要:通過(guò)實(shí)現(xiàn)一次請(qǐng)求來(lái)解釋使用協(xié)程中的實(shí)際問(wèn)題是這篇文章的重點(diǎn)。當(dāng)接收一個(gè)新事件時(shí),啟動(dòng)一個(gè)新的協(xié)程來(lái)對(duì)列表進(jìn)行排序,并在響應(yīng)時(shí)更新。在中啟動(dòng)協(xié)程作為一般模式。因此,在默認(rèn)情況下,在存儲(chǔ)庫(kù)中啟動(dòng)的任何協(xié)程都會(huì)泄露。 原文鏈接:Coroutines On Android (part III): Real work 原文作者:Sean McQuillan 這是一篇關(guān)于在 Android 上使用...

    番茄西紅柿 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<