Я был разработчиком 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% эффективной остановке ЦП.
WeakHashMap
даже если вы правы, что это плохой выбор;)
[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);
}
}
}
}
Это говорит,
Слабая ссылка на ImageView гарантирует, что AsyncTask не препятствует сборке мусора для ImageView и всего, на что он ссылается . Нет никакой гарантии, что ImageView все еще существует после завершения задачи, поэтому вы также должны проверить ссылку в onPostExecute (). ImageView может больше не существовать, если, например, пользователь отходит от действия или если изменение конфигурации происходит до завершения задачи.
Удачного кодирования!
[РЕДАКТИРОВАТЬ] Я нашел действительно хороший пример WeakReference
из Facebook-Android-SDK . Класс ToolTipPopup - это не что иное, как простой класс виджетов, который показывает всплывающую подсказку над видом привязки. Я сделал снимок экрана.
Класс действительно прост (около 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
был A и AnotherClass
был Б.WeakReference
является использование другого класса для реализации интерфейса. Это делается в шаблоне слушателя / наблюдателя .// allow MyClass to get a weak reference to this class void someMethod() { mMyClass = new MyClass(); mMyClass.someMethod(this); }
??
weakreference
объект в doSomething
функции, чтобы не быть null
перед вызовом get
функции.
«Канонизированное» отображение - это когда вы сохраняете один экземпляр рассматриваемого объекта в памяти, а все остальные ищут этот конкретный экземпляр с помощью указателей или некоторого такого механизма. Здесь слабые ссылки могут помочь. Краткий ответ: объекты WeakReference можно использовать для создания указателей на объекты в вашей системе, в то же время позволяя этим объектам утилизироваться сборщиком мусора после выхода из области видимости. Например, если бы у меня был такой код:
class Registry {
private Set registeredObjects = new HashSet();
public void register(Object object) {
registeredObjects.add( object );
}
}
Любой объект, который я регистрирую, никогда не будет возвращен GC, потому что в наборе хранится ссылка на него registeredObjects
. С другой стороны, если я сделаю это:
class Registry {
private Set registeredObjects = new HashSet();
public void register(Object object) {
registeredObjects.add( new WeakReference(object) );
}
}
Затем, когда GC захочет восстановить объекты в наборе, он сможет это сделать. Вы можете использовать эту технику для кэширования, каталогизации и т. Д. См. Ниже ссылки на более подробные обсуждения GC и кэширования.
Ссылка: сборщик мусора и WeakReference