Ответ
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()
}
Нюансы:
- Объект может быть удален в любой момент, даже если память не заполнена
- Не гарантируется время удаления
- Всегда нужно проверять
get()на null перед использованием - Подходит для кэширования дорогих объектов, которые можно пересоздать
Ответ 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.
Короче, инструмент мощный, но с характером. Используй, когда готов к неожиданностям.