Когда WeakReference удаляется в кэше

Ответ

WeakReference удаляется из кэша, когда сборщик мусора (GC) определяет, что на объект больше нет сильных ссылок. В Android это происходит автоматически при нехватке памяти или во время цикла сборки мусора.

Пример использования WeakReference в кэше изображений:

val imageCache = mutableMapOf<String, WeakReference<Bitmap>>()

fun cacheImage(key: String, bitmap: Bitmap) {
    imageCache[key] = WeakReference(bitmap)
}

fun getCachedImage(key: String): Bitmap? {
    return imageCache[key]?.get()
}

Нюансы:

  1. Объект может быть удален в любой момент, даже если память не заполнена
  2. Не гарантируется время удаления
  3. Всегда нужно проверять get() на null перед использованием
  4. Подходит для кэширования дорогих объектов, которые можно пересоздать

Ответ 18+ 🔞

Э, слушай, история про WeakReference — это вообще отдельный вид искусства, ёпта. Представь себе: у тебя есть кэш картинок, и ты такой — о, сейчас я их всех сохраню, чтобы не грузить по сто раз. А потом бац — память кончилась, и система начинает выносить всё, что плохо лежит. Вот тут-то WeakReference и выходит на сцену, как тихий герой, который сам знает, когда ему пора нахуй.

По сути, это такая ссылка-предатель. Пока на объект кто-то ещё смотрит (то есть есть обычная, сильная ссылка), WeakReference держится за него. Но как только последний «нормальный» пользователь отворачивается — всё, объект становится кандидатом на вылет. Сборщик мусора (GC), этот вечный уборщик в твоей оперативке, смотрит на него и думает: «А нахуя ты тут? Никто тебя не держит». И просто выкидывает, без церемоний. В Android это особенно актуально — память там вечно в дефиците, как бензин у таксиста в час пик.

Вот смотри, как это выглядит в коде, тут всё просто:

val imageCache = mutableMapOf<String, WeakReference<Bitmap>>()

fun cacheImage(key: String, bitmap: Bitmap) {
    imageCache[key] = WeakReference(bitmap)
}

fun getCachedImage(key: String): Bitmap? {
    return imageCache[key]?.get()
}

Вроде бы обычный кэш в мапе, да? Но фишка в том, что значение там не сам Bitmap, а эта самая хитрая жопа — WeakReference. Она не мешает GC прийти и сказать: «Этот битмап больше никому не нужен? Отлично, забираем».

А теперь нюансы, без которых можно влететь по полной программе.

Во-первых, объект может испариться в любой момент. Не обязательно ждать, пока память заполнится до предела. Сборщик мусора — существо непредсказуемое, живёт по своим правилам. Может, он просто проходил мимо и решил прибраться. Так что никогда не рассчитывай, что в WeakReference что-то есть. Всегда делай проверку на null, иначе получишь краш, а потом будешь сидеть и думать: «Какого хуя? Только же всё работало!».

Во-вторых, никаких гарантий по времени. Нельзя написать: «Эй, GC, не трогай эту картинку хотя бы пять секунд». Нет, чувак. Как решит, так и будет. Это как оставить еду на столе в общаге — гарантий, что она там будет через час, ноль ебать.

В-третьих, и это главное: перед тем как использовать объект, ты обязан вызвать get() и проверить, не вернулся ли null. Это святое. Иначе это пиздопроебибна ситуация, когда ты пытаешься отрисовать картинку, которой уже нет.

Так когда же это полезно? А вот когда у тебя есть дорогие объекты (те же битмапы, большие массивы данных), которые можно пересоздать, если что. Кэш из WeakReference — это не хранилище, а скорее подсказка системе: «Эй, если совсем припёрло, можешь забрать это первым, мы как-нибудь переживём». Это как отдать соседу последнюю пачку пельменей на время, с условием «вернёшь, если сам не съешь». Доверия, конечно, ебать ноль, но иногда это единственный способ не умереть от OutOfMemoryError.

Короче, инструмент мощный, но с характером. Используй, когда готов к неожиданностям.