Я занимаюсь Java-разработкой 2 года.
Но я никогда не писал WeakReference в своем коде. Как использовать WeakReference, чтобы сделать мое приложение более эффективным, особенно приложение для Android?
Я занимаюсь Java-разработкой 2 года.
Но я никогда не писал WeakReference в своем коде. Как использовать WeakReference, чтобы сделать мое приложение более эффективным, особенно приложение для Android?
Использование WeakReference
в Android ничем не отличается от использования его в простой старой Java.
Вам следует подумать о том, чтобы использовать его всякий раз, когда вам нужна ссылка на объект, но вы не хотите, чтобы эта ссылка защищала объект от сборщика мусора. Классическим примером является кэш, который вы хотите собирать мусором, когда использование памяти становится слишком высоким (часто реализуется с помощью WeakHashMap
).
Не забудьте также проверить SoftReference
и PhantomReference
.
РЕДАКТИРОВАТЬ: Том выразил некоторые опасения по поводу реализации кеширования с WeakHashMap
. Вот статья с описанием проблем: WeakHashMap не кеш!
Том прав в том, что были жалобы на низкую производительность Netbeans из-за WeakHashMap
кэширования .
Я по-прежнему думаю, что было бы неплохо реализовать кэш с WeakHashMap
, а затем сравнить его с вашим собственным скрученным вручную кешем, реализованным с SoftReference
. В реальном мире вы, вероятно, не стали бы использовать ни одно из этих решений, поскольку имеет смысл использовать стороннюю библиотеку, например Apache JCS.
WeakHashMap
, используемый в качестве кеша, является фатальным. Записи могут быть удалены, как только они будут созданы. Вероятно, этого не произойдет, когда вы тестируете, но вполне может при использовании. Следует отметить, что благодаря этому NetBeans может быть эффективно остановлен на 100%.
- person Tom Hawtin - tackline; 14.07.2010
WeakHashMap
, даже если вы правы, что это плохой выбор;)
- person dbyrne; 14.07.2010
[EDIT2] Я нашел еще один хороший пример WeakReference
. Обработка растровых изображений вне потока пользовательского интерфейса на странице Эффективное отображение растровых изображений показано одно использование WeakReference
в AsyncTask.
class BitmapWorkerTask extends AsyncTask<Integer, Void, Bitmap> {
private final WeakReference<ImageView> imageViewReference;
private int data = 0;
public BitmapWorkerTask(ImageView imageView) {
// Use a WeakReference to ensure the ImageView can be garbage collected
imageViewReference = new WeakReference<ImageView>(imageView);
}
// Decode image in background.
@Override
protected Bitmap doInBackground(Integer... params) {
data = params[0];
return decodeSampledBitmapFromResource(getResources(), data, 100, 100));
}
// Once complete, see if ImageView is still around and set bitmap.
@Override
protected void onPostExecute(Bitmap bitmap) {
if (imageViewReference != null && bitmap != null) {
final ImageView imageView = imageViewReference.get();
if (imageView != null) {
imageView.setImageBitmap(bitmap);
}
}
}
}
Он говорит:
WeakReference для ImageView гарантирует, что AsyncTask не препятствует сборке мусора для ImageView и всего, на что он ссылается. Нет никакой гарантии, что ImageView все еще существует после завершения задачи, поэтому вы также должны проверить ссылку в onPostExecute (). ImageView может больше не существовать, если, например, пользователь уходит от операции или если изменение конфигурации происходит до завершения задачи.
Удачного кодирования!
[EDIT] Я нашел действительно хороший пример WeakReference
из facebook-android-sdk . ToolToolTipPopup.java"> Инструмент ничего но простой класс виджета, который показывает всплывающую подсказку над представлением привязки. Я сделал снимок экрана.
Класс действительно простой (около 200 строк) и достойный внимания. В этом классе класс WeakReference
используется для хранения ссылки на представление привязки, что имеет смысл, поскольку позволяет собирать мусор для представления привязки, даже если экземпляр всплывающей подсказки живет дольше, чем его представление привязки.
Удачного кодирования! :)
Приведу один рабочий пример класса WeakReference
. Это небольшой фрагмент кода из виджета платформы Android под названием AutoCompleteTextView
.
Короче говоря, WeakReference
класс используется для хранения View
объекта для предотвращения утечка памяти в этом примере.
Я просто скопирую и вставлю класс PopupDataSetObserver, который является вложенным классом AutoCompleteTextView
. Это действительно просто, и комментарии хорошо объясняют класс. Удачного кодирования! :)
/**
* Static inner listener that keeps a WeakReference to the actual AutoCompleteTextView.
* <p>
* This way, if adapter has a longer life span than the View, we won't leak the View, instead
* we will just leak a small Observer with 1 field.
*/
private static class PopupDataSetObserver extends DataSetObserver {
private final WeakReference<AutoCompleteTextView> mViewReference;
private PopupDataSetObserver(AutoCompleteTextView view) {
mViewReference = new WeakReference<AutoCompleteTextView>(view);
}
@Override
public void onChanged() {
final AutoCompleteTextView textView = mViewReference.get();
if (textView != null && textView.mAdapter != null) {
// If the popup is not showing already, showing it will cause
// the list of data set observers attached to the adapter to
// change. We can't do it from here, because we are in the middle
// of iterating through the list of observers.
textView.post(updateRunnable);
}
}
private final Runnable updateRunnable = new Runnable() {
@Override
public void run() {
final AutoCompleteTextView textView = mViewReference.get();
if (textView == null) {
return;
}
final ListAdapter adapter = textView.mAdapter;
if (adapter == null) {
return;
}
textView.updateDropDownForFilter(adapter.getCount());
}
};
}
И PopupDataSetObserver
используется в настройке адаптера.
public <T extends ListAdapter & Filterable> void setAdapter(T adapter) {
if (mObserver == null) {
mObserver = new PopupDataSetObserver(this);
} else if (mAdapter != null) {
mAdapter.unregisterDataSetObserver(mObserver);
}
mAdapter = adapter;
if (mAdapter != null) {
//noinspection unchecked
mFilter = ((Filterable) mAdapter).getFilter();
adapter.registerDataSetObserver(mObserver);
} else {
mFilter = null;
}
mPopup.setAdapter(mAdapter);
}
Последняя вещь. Я также хотел узнать рабочий пример WeakReference
в приложении Android, и я смог найти некоторые образцы в его официальных примерах приложений. Но я действительно не мог понять, как используются некоторые из них. Например, ThreadSample и DisplayingBitmaps приложения используют WeakReference
в своем коде, но после выполнения нескольких тестов я обнаружил, что метод get () никогда не возвращает null
, потому что указанный объект представления перерабатывается в адаптерах, а не сборщиком мусора.
Некоторые другие ответы кажутся неполными или слишком длинными. Вот общий ответ.
Вы можете сделать следующие шаги:
WeakReference
переменнуюMyClass
имеет слабую ссылку на AnotherClass
.
public class MyClass {
// 1. Create a WeakReference variable
private WeakReference<AnotherClass> mAnotherClassReference;
// 2. Set the weak reference (nothing special about the method name)
void setWeakReference(AnotherClass anotherClass) {
mAnotherClassReference = new WeakReference<>(anotherClass);
}
// 3. Use the weak reference
void doSomething() {
AnotherClass anotherClass = mAnotherClassReference.get();
if (anotherClass == null) return;
// do something with anotherClass
}
}
AnotherClass
имеет сильную ссылку на MyClass
.
public class AnotherClass {
// strong reference
MyClass mMyClass;
// allow MyClass to get a weak reference to this class
void someMethod() {
mMyClass = new MyClass();
mMyClass.setWeakReference(this);
}
}
MyClass
был А и AnotherClass
был Б.WeakReference
является другой класс, реализующий интерфейс. Это делается в шаблоне слушателя / наблюдателя.// allow MyClass to get a weak reference to this class void someMethod() { mMyClass = new MyClass(); mMyClass.someMethod(this); }
??
- person likejudo; 03.11.2019
weakreference
в функции doSomething
не был null
перед вызовом функции get
.
- person Behrouz.M; 12.05.2020
«Каноническое» отображение - это когда вы храните один экземпляр рассматриваемого объекта в памяти, а все остальные ищут этот конкретный экземпляр с помощью указателей или другого подобного механизма. Здесь могут помочь слабые ссылки. Короткий ответ заключается в том, что объекты WeakReference можно использовать для создания указателей на объекты в вашей системе, в то же время позволяя этим объектам быть возвращенными сборщиком мусора, когда они выходят из сфера. Например, если бы у меня был такой код:
class Registry {
private Set registeredObjects = new HashSet();
public void register(Object object) {
registeredObjects.add( object );
}
}
Любой зарегистрированный мной объект никогда не будет возвращен сборщиком мусора, потому что на него есть ссылка, хранящаяся в наборе registeredObjects
. С другой стороны, если я сделаю это:
class Registry {
private Set registeredObjects = new HashSet();
public void register(Object object) {
registeredObjects.add( new WeakReference(object) );
}
}
Затем, когда GC захочет вернуть объекты в Set, он сможет это сделать. Вы можете использовать этот метод для кэширования, каталогизации и т. Д. См. Ниже ссылки на более подробные обсуждения GC и кеширования.
Ссылка: Сборщик мусора и WeakReference