Yanıtlar:
Bir Kullanarak WeakReference
Android'de düz eski Java birini kullanarak daha farklı değildir. Ayrıntılı bir açıklama veren harika bir kılavuz: Zayıf Referansları Anlama .
Bir nesneye başvurmak istediğinizde bir tane kullanmayı düşünmelisiniz, ancak nesneyi çöp toplayıcıdan korumak için bu başvuruyu istemezsiniz. Klasik bir örnek, bellek kullanımı çok yükseldiğinde (genellikle uygulandığında WeakHashMap
) çöp toplanmasını istediğiniz bir önbellektir .
Kontrol etmeyi unutmayın SoftReference
ve PhantomReference
de.
EDIT: Tom ile önbellek uygulama konusunda bazı endişeler dile getirdi WeakHashMap
. Sorunları ortaya koyan bir makale: WeakHashMap bir önbellek değil!
Tom, önbellekleme nedeniyle zayıf Netbeans performansı hakkında şikayetler olduğu konusunda haklı WeakHashMap
.
Hala bir önbellek uygulamak WeakHashMap
ve daha sonra kendi el ile haddelenmiş önbellek ile karşılaştırıldığında karşılaştırmak için iyi bir öğrenme deneyimi olacağını düşünüyorum SoftReference
. Gerçek dünyada, muhtemelen bu çözümlerden hiçbirini kullanmazsınız, çünkü Apache JCS gibi bir üçüncü taraf kütüphanesi kullanmak daha mantıklıdır .
WeakHashMap
önbellek olarak kullanılan ölümcül. Girişler oluşturulur oluşturulmaz kaldırılabilir. Bu muhtemelen test ederken gerçekleşmez, ancak kullanımda iyi olabilir. NetBeans bununla% 100 etkili bir CPU durağına getirilebilir.
WeakHashMap
kötü bir seçim olduğunu doğru olsa bile önbellekleri sık sık uygulanan doğruydu;)
[EDIT2] için iyi bir örnek daha buldum WeakReference
. Bitmap'leri İşleme Bitmap'leri Görüntüleme eğitim kılavuzundaki UI İş Parçacığı sayfasından Kapalı,WeakReference
AsyncTask'te bir kullanımını gösterir .
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);
}
}
}
}
Diyor ki,
ImageView'e yapılan WeakReference, AsyncTask'in ImageView ve referans aldığı herhangi bir şeyin çöp toplanmasını engellememesini sağlar . Görev bittiğinde ImageView'in hala orada olduğuna dair bir garanti yoktur, bu nedenle onPostExecute () içindeki referansı da kontrol etmeniz gerekir. Örneğin, kullanıcı etkinlikten uzaklaşırsa veya görev tamamlanmadan bir yapılandırma değişikliği olursa ImageView artık mevcut olmayabilir.
Mutlu kodlama!
[EDIT] Ben gerçekten iyi bir örnek buldum WeakReference
dan facebook-android-sdk . ToolTipPopup sınıfı, çapa görünümünün üzerinde araç ipucunu gösteren basit bir widget sınıfından başka bir şey değildir. Bir ekran görüntüsü yakaladım.
Sınıf gerçekten basit (yaklaşık 200 satır) ve bakmak için layık. Bu sınıfta, WeakReference
sınıf, çapa görünümüne referans tutmak için kullanılır, bu da mantıklıdır, çünkü bir araç ipucu örneği, çapa görünümünden daha uzun sürse bile çapa görünümünün çöp toplanmasını mümkün kılar.
Mutlu kodlama! :)
WeakReference
Sınıfın çalışan bir örneğini paylaşayım. Android çerçeve widget denilen küçük bir kod snippet AutoCompleteTextView
.
Kısacası, WeakReference
sınıf bu örnekte bellek sızıntısını önlemek için nesneyi tutmak için kullanılır .View
Ben sadece iç içe bir sınıf olan PopupDataSetObserver sınıfını kopyalayıp yapıştıracağım AutoCompleteTextView
. Gerçekten basit ve yorumlar sınıfı iyi açıklıyor. Mutlu kodlama! :)
/**
* 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());
}
};
}
Ve PopupDataSetObserver
adaptörün ayarlanmasında kullanılır.
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);
}
Son bir şey. Ayrıca WeakReference
Android uygulamasında çalışan bir örnek bilmek istedim ve resmi örnek uygulamalarında bazı örnekler bulabilirim. Ama bazılarının kullanımını gerçekten anlayamadım. Örneğin, ThreadSample ve DisplayingBitmaps uygulamaları WeakReference
kodunda kullanır, ancak birkaç test çalıştırdıktan sonra null
, referans (get) nesnesi, toplanan çöp yerine adaptörlerde geri dönüştürüldüğü için get () yönteminin hiçbir zaman geri dönmediğini öğrendim .
Diğer cevapların bazıları eksik veya aşırı uzun görünüyor. İşte genel bir cevap.
Aşağıdaki adımları uygulayabilirsiniz:
WeakReference
Değişken oluşturmaMyClass
zayıf bir referansı var 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
güçlü bir referansı var 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, ve AnotherClass
B idi.WeakReference
, başka bir sınıfın arabirim uygulamasıdır. Bu, Dinleyici / Gözlemci Düzeninde yapılır .// allow MyClass to get a weak reference to this class void someMethod() { mMyClass = new MyClass(); mMyClass.someMethod(this); }
??
weakreference
nesnenin kendisini doSomething
fonksiyonda kontrol etmeniz gerekir . null
get
"Standartlaştırılmış" eşleme, söz konusu nesnenin bir örneğini bellekte tuttuğunuz yerdir ve diğerlerinin tümü bu örneği işaretçiler veya somesuch mekanizması aracılığıyla arar. Burada zayıflar referansları yardımcı olabilir. Kısa yanıt, WeakReference nesnelerinin sisteminizdeki nesnelere işaretçiler oluşturmak için kullanılabilmeleri ve bu nesnelerin kapsam dışına çıktıklarında çöp toplayıcı tarafından geri kazanılmalarına izin vermesidir . Örneğin böyle bir kod vardı:
class Registry {
private Set registeredObjects = new HashSet();
public void register(Object object) {
registeredObjects.add( object );
}
}
Kaydettiğim herhangi bir nesne, GC tarafından geri alınmayacaktır, çünkü kümesinde saklanan bir referans vardır registeredObjects
. Öte yandan bunu yaparsam:
class Registry {
private Set registeredObjects = new HashSet();
public void register(Object object) {
registeredObjects.add( new WeakReference(object) );
}
}
Daha sonra GC, Set'teki nesneleri geri almak istediğinde bunu yapabilir. Bu tekniği önbellekleme, kataloglama vb. İçin kullanabilirsiniz. GC ve önbelleğe alma hakkında daha ayrıntılı tartışmalara başvurmak için aşağıya bakın.