Saya telah menjadi pengembang java selama 2 tahun.
Tapi saya belum pernah menulis Referensi Lemah dalam kode saya. Bagaimana cara menggunakan WeakReference untuk membuat aplikasi saya lebih efisien terutama aplikasi Android?
Saya telah menjadi pengembang java selama 2 tahun.
Tapi saya belum pernah menulis Referensi Lemah dalam kode saya. Bagaimana cara menggunakan WeakReference untuk membuat aplikasi saya lebih efisien terutama aplikasi Android?
Jawaban:
Menggunakan WeakReference
di Android tidak ada bedanya dengan menggunakannya di Jawa kuno. Berikut ini adalah panduan hebat yang memberikan penjelasan terperinci: Memahami Referensi Lemah .
Anda harus berpikir tentang menggunakan satu setiap kali Anda memerlukan referensi ke suatu objek, tetapi Anda tidak ingin referensi itu untuk melindungi objek dari pengumpul sampah. Contoh klasik adalah cache yang Anda inginkan menjadi sampah yang dikumpulkan ketika penggunaan memori terlalu tinggi (sering diimplementasikan dengan WeakHashMap
).
Pastikan untuk memeriksa SoftReference
dan PhantomReference
juga.
EDIT: Tom telah menimbulkan beberapa kekhawatiran tentang penerapan cache WeakHashMap
. Berikut ini adalah artikel yang menjelaskan masalahnya: WeakHashMap bukan cache!
Tom benar bahwa ada keluhan tentang kinerja Netbeans yang buruk karena WeakHashMap
caching.
Saya masih berpikir itu akan menjadi pengalaman belajar yang baik untuk mengimplementasikan cache WeakHashMap
dan kemudian membandingkannya dengan cache linting tangan Anda yang diimplementasikan SoftReference
. Di dunia nyata, Anda mungkin tidak akan menggunakan salah satu dari solusi ini, karena lebih masuk akal untuk menggunakan perpustakaan pihak ke-3 seperti Apache JCS .
WeakHashMap
digunakan sebagai cache fatal. Entri dapat dihapus segera setelah dibuat. Ini mungkin tidak akan terjadi ketika Anda menguji, tetapi mungkin baik saat digunakan. Sebagai catatan, NetBeans dapat dibawa ke CPU 100% yang efektif dengan ini.
WeakHashMap
bahkan jika Anda benar bahwa itu adalah pilihan yang buruk;)
[EDIT2] Saya menemukan contoh bagus lain dari WeakReference
. Memproses Bitmap Dari halaman Thread UI dalam Menampilkan Bitmap Panduan pelatihan yang efisien , menunjukkan satu penggunaan WeakReference
dalam 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);
}
}
}
}
Ia mengatakan,
WeakReference to ImageView memastikan bahwa AsyncTask tidak mencegah ImageView dan referensi apa pun dari pengumpulan sampah . Tidak ada jaminan bahwa ImageView masih ada ketika tugas selesai, jadi Anda juga harus memeriksa referensi di onPostExecute (). ImageView mungkin tidak ada lagi, jika misalnya, pengguna menavigasi menjauh dari aktivitas atau jika perubahan konfigurasi terjadi sebelum tugas selesai.
Selamat coding!
[EDIT] Saya menemukan contoh yang sangat bagus WeakReference
dari facebook-android-SDK . Kelas ToolTipPopup tidak lain adalah kelas widget sederhana yang menunjukkan tooltip di atas tampilan jangkar. Saya menangkap tangkapan layar.
Kelasnya sangat sederhana (sekitar 200 baris) dan layak untuk dilihat. Di kelas itu, WeakReference
kelas digunakan untuk memegang referensi ke tampilan jangkar, yang masuk akal, karena memungkinkan untuk tampilan jangkar menjadi sampah yang dikumpulkan bahkan ketika instance tooltip hidup lebih lama daripada tampilan jangkar.
Selamat coding! :)
Izinkan saya membagikan satu contoh kerja WeakReference
kelas. Ini sedikit cuplikan kode dari widget kerangka Android yang disebut AutoCompleteTextView
.
Singkatnya, WeakReference
kelas digunakan untuk memegang View
objek untuk mencegah kebocoran memori dalam contoh ini.
Saya hanya akan menyalin dan menempelkan kelas PopupDataSetObserver, yang merupakan kelas bersarang AutoCompleteTextView
. Ini sangat sederhana dan komentarnya menjelaskan kelas dengan baik. Selamat coding! :)
/**
* 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());
}
};
}
Dan PopupDataSetObserver
digunakan dalam pengaturan adaptor.
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);
}
Satu hal terakhir. Saya juga ingin tahu contoh kerja WeakReference
dalam aplikasi Android, dan saya bisa menemukan beberapa sampel dalam aplikasi sampel resminya. Tetapi saya benar-benar tidak dapat memahami penggunaan beberapa dari mereka. Sebagai contoh, aplikasi ThreadSample dan DisplayingBitmaps digunakan WeakReference
dalam kodenya, tetapi setelah menjalankan beberapa tes, saya menemukan bahwa metode get () tidak pernah kembali null
, karena objek tampilan yang direferensikan didaur ulang dalam adaptor, bukan sampah yang dikumpulkan.
Beberapa jawaban lain tampaknya tidak lengkap atau terlalu panjang. Inilah jawaban umum.
Anda dapat melakukan langkah-langkah berikut:
WeakReference
variabelMyClass
memiliki referensi yang lemah untuk 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
memiliki referensi yang kuat untuk 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
adalah A dan AnotherClass
B.WeakReference
adalah memiliki kelas lain mengimplementasikan antarmuka. Ini dilakukan dalam Pola Pendengar / Pengamat .// allow MyClass to get a weak reference to this class void someMethod() { mMyClass = new MyClass(); mMyClass.someMethod(this); }
??
weakreference
objek itu sendiri doSomething
agar tidak berfungsi null
sebelum memanggil get
fungsi.
Pemetaan "dikanonik" adalah di mana Anda menyimpan satu instance objek yang bersangkutan dalam memori dan semua yang lain mencari contoh tertentu melalui pointer atau mekanisme semacam itu. Di sinilah referensi lemah dapat membantu. Jawaban singkatnya adalah bahwa objek WeakReference dapat digunakan untuk membuat pointer ke objek di sistem Anda sambil tetap membiarkan objek-objek tersebut untuk direklamasi oleh pengumpul sampah begitu mereka keluar dari ruang lingkup. Sebagai contoh jika saya memiliki kode seperti ini:
class Registry {
private Set registeredObjects = new HashSet();
public void register(Object object) {
registeredObjects.add( object );
}
}
Objek apa pun yang saya daftarkan tidak akan pernah direklamasi oleh GC karena ada referensi untuk itu disimpan dalam set registeredObjects
. Di sisi lain jika saya melakukan ini:
class Registry {
private Set registeredObjects = new HashSet();
public void register(Object object) {
registeredObjects.add( new WeakReference(object) );
}
}
Kemudian ketika GC ingin mengklaim kembali objek dalam Set itu akan dapat melakukannya. Anda dapat menggunakan teknik ini untuk caching, katalog, dll. Lihat di bawah untuk referensi untuk diskusi yang lebih mendalam tentang GC dan caching.