He sido desarrollador de Java durante 2 años.
Pero nunca he escrito una WeakReference en mi código. ¿Cómo usar WeakReference para hacer que mi aplicación sea más eficiente, especialmente la aplicación de Android?
He sido desarrollador de Java durante 2 años.
Pero nunca he escrito una WeakReference en mi código. ¿Cómo usar WeakReference para hacer que mi aplicación sea más eficiente, especialmente la aplicación de Android?
Respuestas:
Usar un WeakReferenceen Android no es diferente de usar uno en Java antiguo. Aquí hay una gran guía que brinda una explicación detallada: Comprender las referencias débiles .
Debería pensar en usar uno cada vez que necesite una referencia a un objeto, pero no desea que esa referencia proteja el objeto del recolector de basura. Un ejemplo clásico es un caché en el que desea recolectar basura cuando el uso de memoria es demasiado alto (a menudo implementado conWeakHashMap ).
Asegúrese de revisar SoftReferenceyPhantomReference también.
EDITAR: Tom ha planteado algunas preocupaciones sobre la implementación de un caché con WeakHashMap. Aquí hay un artículo que presenta los problemas: WeakHashMap no es un caché!
Tom tiene razón en que ha habido quejas sobre el bajo rendimiento de Netbeans debido aWeakHashMap almacenamiento caché.
Todavía creo que sería una buena experiencia de aprendizaje implementar un caché WeakHashMapy luego compararlo con su propio caché enrollado a mano implementado SoftReference. En el mundo real, probablemente no usaría ninguna de estas soluciones, ya que tiene más sentido usar una biblioteca de terceros como Apache JCS .
WeakHashMapusado como caché es fatal. Las entradas se pueden eliminar tan pronto como se crean. Esto probablemente no sucederá cuando esté realizando la prueba, pero puede ocurrir cuando esté en uso. Es de destacar que NetBeans puede llegar a una parada efectiva del 100% de la CPU con esto.
WeakHashMapincluso si usted es correcto, es una mala elección;)
[EDIT2] Encontré otro buen ejemplo de WeakReference. Procesar mapas de bits fuera de la página de subprocesos de la interfaz de usuario en la guía de capacitación Visualización eficiente de WeakReferencemapas de bits , muestra un uso de 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);
}
}
}
}
Dice,
La WeakReference a ImageView garantiza que AsyncTask no impida que se recoja basura ImageView y cualquier cosa a la que haga referencia . No hay garantía de que ImageView siga existiendo cuando finalice la tarea, por lo que también debe verificar la referencia en onPostExecute (). Es posible que ImageView ya no exista, si, por ejemplo, el usuario se aleja de la actividad o si se produce un cambio de configuración antes de que finalice la tarea.
¡Feliz codificación!
[EDIT] me encontré con un muy buen ejemplo de WeakReferencedesde facebook-android-sdk . La clase ToolTipPopup no es más que una clase de widget simple que muestra información sobre herramientas sobre la vista de anclaje. Capturé una captura de pantalla.

La clase es realmente simple (alrededor de 200 líneas) y digna de ver. En esa clase,WeakReference clase se usa para mantener referencia a la vista de anclaje, lo que tiene mucho sentido, ya que hace posible que la vista de anclaje se recolecte basura incluso cuando una instancia de información sobre herramientas dura más que su vista de anclaje.
¡Feliz codificación! :)
Permítanme compartir un ejemplo WeakReferencepráctico de clase. Es un pequeño fragmento de código del widget de marco de Android llamado AutoCompleteTextView.
En resumen, la WeakReference clase se usa para contener View objetos para evitar pérdidas de memoria en este ejemplo.
Copiaré y pegaré la clase PopupDataSetObserver, que es una clase anidada de AutoCompleteTextView. Es realmente simple y los comentarios explican bien la clase. ¡Feliz codificación! :)
/**
* 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());
}
};
}
Y PopupDataSetObserverse usa para configurar el adaptador.
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);
}
Una última cosa. También quería saber ejemplos de trabajo WeakReferenceen aplicaciones de Android, y pude encontrar algunas muestras en sus aplicaciones de muestra oficiales. Pero realmente no podía entender el uso de algunos de ellos. Por ejemplo, ThreadSample y DisplayingBitmaps aplicaciones utilizan WeakReferenceen su código, pero después de correr varias pruebas, he encontrado que el método get () no vuelve nunca null, porque la vista referenciada objeto se recicla en los adaptadores, en lugar de basura recogida.
Algunas de las otras respuestas parecen incompletas o demasiado largas. Aquí hay una respuesta general.
Puedes hacer los siguientes pasos:
WeakReference variableMyClasstiene una referencia débil a 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
}
}
AnotherClasstiene una fuerte referencia a 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);
}
}
MyClassera A y AnotherClassfue B.WeakReferencees hacer que otra clase implemente una interfaz. Esto se hace en el patrón de escucha / observador .// allow MyClass to get a weak reference to this class void someMethod() { mMyClass = new MyClass(); mMyClass.someMethod(this); }??
weakreferenceobjeto en sí mismo en la doSomethingfunción para que no esté nullantes de llamar a la getfunción.
Un mapeo "canonicalizado" es donde mantiene una instancia del objeto en cuestión en la memoria y todas las demás buscan esa instancia en particular a través de punteros o algún mecanismo. Aquí es donde las referencias de los débiles pueden ayudar. La respuesta corta es que los objetos WeakReference se pueden usar para crear punteros a objetos en su sistema y al mismo tiempo permitir que esos objetos sean reclamados por el recolector de basura una vez que pasan del alcance. Por ejemplo, si tuviera un código como este:
class Registry {
private Set registeredObjects = new HashSet();
public void register(Object object) {
registeredObjects.add( object );
}
}
Cualquier objeto que registre nunca será reclamado por el GC porque hay una referencia a él almacenado en el conjunto de registeredObjects. Por otro lado si hago esto:
class Registry {
private Set registeredObjects = new HashSet();
public void register(Object object) {
registeredObjects.add( new WeakReference(object) );
}
}
Luego, cuando el GC quiera reclamar los objetos en el Conjunto, podrá hacerlo. Puede utilizar esta técnica para el almacenamiento en caché, la catalogación, etc. Consulte a continuación las referencias a debates mucho más detallados sobre GC y almacenamiento en caché.