[英]Firebase addOnSuccessListener callback running context throws `NetworkOnMainThreadException`
假設我有一個存儲庫 class,它定義了一種從 Firebase 存儲中檢索圖像的方法,並定義了一個成功偵聽器,該偵聽器調用從視圖 model 定義的回調
fun getAdImg(imgId: String, callback: (stream: Bitmap?) -> Unit) {
storage.child(FOLDER).child(imgId+EXTENSION).stream
.addOnSuccessListener {
callback(BitmapFactory.decodeStream(it.stream))
Log.i(TAG, "getAdImg success")
}
.addOnCanceledListener {
Log.e(TAG, "getAdImg canceled")
}
.addOnFailureListener {
Log.e(TAG, "getAdImg failure")
}
}
定義回調並調用存儲庫的視圖 model 中的 function 如下
fun loadImage(imgId: String?) {
imgId?.let { id ->
if (_img.value == null) {
viewModelScope.launch (context = IO) {
AdvertisementRepository.getInstance().getAdImg(id) { bitmap ->
_img.postValue(bitmap)
}
}
}
}
}
我有一些問題:
addOnSuccessListener
中的 addOnSuccessListener 定義的偵聽器的生命周期是什么?callback
function 的 scope 是什么?BitmapFactory.decodeStream(it.stream)
將拋出一個android.os.NetworkOnMainThreadException
,由於調用decodeStream
function 的上下文,這似乎是一個異常由存儲庫 class 中的 addOnSuccessListener 定義的偵聽器的生命周期是什么?
你在這里使用它的方式,它沒有生命周期。 回調將無限期持續。
在監聽器中調用回調 function 的 scope 是什么?
它沒有協程 scope。 只要結果准備好,就會在主線程上調用回調。
當我嘗試運行此代碼時,
BitmapFactory.decodeStream(it.stream)
將拋出一個 android.os.NetworkOnMainThreadException,由於調用 decodeStream function 的上下文,這似乎是一個異常
是的,因為回調是在主線程上調用的,並且 decodeStream 執行 I/O,所以如果啟用嚴格模式來檢測主線程上的 I/O,您會期望它會拋出異常。 這就是為什么 getStream() 的 API 文檔說:
通過 InputStream 在此 StorageReference 處異步下載 object。 應該在通過 addOnSuccessListener(Executor, OnSuccessListener) 注冊以在后台線程上運行的 OnSuccessListener 上讀取 InputStream
文檔建議您安排在使用 Executor 的主線程以外的線程上調用回調。 或者,您可以使用協程,但 API 不支持 Kotlin,因此您需要自行安排。 有一個庫可以幫助將任務轉換為協程使用。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.