Как правильно подписаться на событие загрузки изображение в общем списке задач для item в LazyColumun Compose

Я с сервера получаю список изображений и в своей ленте их отображаю, но проблема в том, изображения могут быть большого размера, до 5 мб и мне нужно отобразить их всё, а их может быть до 50 шт в одном item.

Я не могу использовать Coil. Сервер использует Amazon они генерируют каждый раз уникальный url.

По этому я кеширую изображения в память устройства и отображаю. Сначала я думал загрузить их всё стразу, просто вызвав функцию загрузки файла в каждом item LaunchedEffect, а коллбеком вернуть путь к изображению.

Но я получал ошибку:

java.lang.OutOfMemoryError: Failed to allocate a 16 byte allocation with 199440 free bytes and 194KB until OOM, target footprint 201326592, growth limit 201326592; giving up on allocation because <1% of heap free after GC.

Поэтому я придумал другой подход вроде задач и скачиваю изображения последовательно, это помогло мне избавиться от ошибки и зависания устройства.

Но я не знаю как правильно подписаться на обновления в своем ItemPhoto чтобы он знал, что изображение с id к примеру 1 - 100 было закешировано на диске и его можно отобразить по этому пути.

Вот мой код, он полностью демонстрирует то что не gif.

@HiltViewModel
class BigFileViewModel  @Inject constructor(
    val serviceApi : ServiceApi
) : ViewModel(){
    private val channel = Channel<DownloadImage>()
    
    var loadedImagesList  = mutableStateOf<List<DownloadImage>?>(null)
        private set
    
    init{
        CoroutineScope(Dispatchers.Default).launch {
            for (operation in channel) {
                CoroutineScope(Dispatchers.Default).async {
                    serviceApi.downloadFileLink(operation.imageLink).collect{response->
                        if(response is NetworkResponse.Success){
                            updateItem(DownloadImage(operation.itemId, response.data))
                        }
                    }
                }
            }
        }
    }

    private fun updateItem(downloadImage: DownloadImage) {
        loadedImagesList .value = loadedImagesList .value.orEmpty() + downloadImage
    }
    fun downloadPhoto(itemId : Int, url : String){
        viewModelScope.launch {
            channel.send(DownloadImage(itemId, url))
        }
    }
}

@Composable
fun BigFileList(bigFileViewModel : BigFileViewModel = hiltViewModel()){
    LazyColumn(content = {
        items(1){
            FlowRowItem(bigFileViewModel)
        }
    })
}

@OptIn(ExperimentalLayoutApi::class)
@Composable
fun FlowRowItem( bigFileViewModel : BigFileViewModel){

    FlowRow(
        modifier = Modifier
            .padding(8.dp),
        horizontalArrangement = Arrangement.Start
    ) {
        for(item in 0..23){
            ItemPhoto((0..10000).random(), imageList.random(), bigFileViewModel)
        }
    }
}

@Composable
fun ItemPhoto(itemId : Int, setLink : String, bigFileViewModel : BigFileViewModel){
    val link = remember { mutableStateOf<String?>( null ) }
    val updateList by bigFileViewModel.loadedImagesList

    LaunchedEffect(key1 = Unit, block = {
        bigFileViewModel.downloadPhoto(itemId, setLink)
    })

    LaunchedEffect(key1 = updateList, block = {
        updateList?.forEach {item->
            if(item.itemId == itemId){
                link.value = item.imageLink
            }
        }
    })

    link.value?.let {url->
        Image(
            painter = rememberAsyncImagePainter(
                url,
                filterQuality = FilterQuality.None,
            ),
            contentDescription = null,
            modifier = itemModifier2,
            contentScale = ContentScale.Crop
        )
    } ?: run {
        Box(contentAlignment = Alignment.Center) {
           Column(
               modifier = itemModifier2,
               verticalArrangement = Arrangement.spacedBy(5.dp, Alignment.Top),
               horizontalAlignment = Alignment.CenterHorizontally,
           ) {
               CircularProgressIndicator()
               Text("$itemId")
           }
        }
    }
}

введите сюда описание изображения


Ответы (0 шт):