मैं 2 साल से जावा डेवलपर रहा हूं।
लेकिन मैंने अपने कोड में कभी भी WeakReference नहीं लिखा है। अपने एप्लिकेशन को विशेष रूप से Android एप्लिकेशन को अधिक कुशल बनाने के लिए WeakReference का उपयोग कैसे करें?
मैं 2 साल से जावा डेवलपर रहा हूं।
लेकिन मैंने अपने कोड में कभी भी WeakReference नहीं लिखा है। अपने एप्लिकेशन को विशेष रूप से Android एप्लिकेशन को अधिक कुशल बनाने के लिए WeakReference का उपयोग कैसे करें?
जवाबों:
WeakReference
एंड्रॉइड में उपयोग करना सादे पुराने जावा में एक का उपयोग करने से अलग नहीं है। यहां एक महान मार्गदर्शक है जो एक विस्तृत विवरण देता है: कमजोर संदर्भों को समझना ।
जब भी आपको किसी ऑब्जेक्ट के संदर्भ की आवश्यकता हो, तो आपको एक का उपयोग करने के बारे में सोचना चाहिए, लेकिन आप उस संदर्भ को कचरा कलेक्टर से बचाने के लिए नहीं चाहते हैं। एक क्लासिक उदाहरण एक कैश है जिसे आप कचरा एकत्र करना चाहते हैं जब मेमोरी उपयोग बहुत अधिक हो जाता है (अक्सर इसके साथ लागू किया जाता है WeakHashMap
)।
बाहर SoftReference
और PhantomReference
साथ ही जांच करना सुनिश्चित करें ।
EDIT: टॉम ने कैश को लागू करने को लेकर कुछ चिंताएं जताई हैं WeakHashMap
। यहाँ समस्याओं को दूर करने वाला एक लेख है: WeakHashMap कैश नहीं है!
टॉम सही है कि कैशिंग के कारण खराब नेटबेंस के प्रदर्शन के बारे में शिकायतें आई हैं WeakHashMap
।
मुझे अभी भी लगता है कि कैश को लागू करना एक अच्छा सीखने का अनुभव होगा WeakHashMap
और फिर इसे अपने हाथ से रोल किए गए कैश के साथ तुलना करें SoftReference
। वास्तविक दुनिया में, आप शायद इनमें से किसी भी समाधान का उपयोग नहीं करेंगे, क्योंकि यह अपाचे जेसीएस जैसी 3 पार्टी लाइब्रेरी का उपयोग करने के लिए अधिक समझ में आता है ।
WeakHashMap
कैश के रूप में इस्तेमाल घातक है। जैसे ही वे बनाए जाते हैं, प्रविष्टियाँ निकाली जा सकती हैं। यह शायद तब नहीं होगा जब आप परीक्षण कर रहे हैं, लेकिन उपयोग में होने पर अच्छी तरह से हो सकता है। ध्यान से, नेटबीन्स को इसके द्वारा प्रभावी 100% सीपीयू स्टॉप पर लाया जा सकता है।
WeakHashMap
भले ही आप सही हों कि यह एक बुरा विकल्प है;)
[EDIT2] मुझे इसका एक और अच्छा उदाहरण मिला WeakReference
। Bitmaps को प्रदर्शित करने के लिए UI थ्रेड पृष्ठ से बिटमैप को संसाधित करना कुशल प्रशिक्षण मार्गदर्शिका, 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 का WeakReference यह सुनिश्चित करता है कि AsyncTask ImageView को रोकती नहीं है और जो कुछ भी इसे संदर्भित करता है वह कचरा एकत्र होने से रोकता है । इस बात की कोई गारंटी नहीं है कि जब कार्य पूरा हो जाता है तब ImageView आसपास होता है, इसलिए आपको onPostExecute () में संदर्भ की जांच करनी चाहिए। ImageView अब मौजूद नहीं हो सकता है, उदाहरण के लिए, यदि उपयोगकर्ता गतिविधि से दूर हो जाता है या यदि कार्य समाप्त होने से पहले कॉन्फ़िगरेशन परिवर्तन होता है।
हैप्पी कोडिंग!
[संपादित करें] मुझे facebook-android-sdkWeakReference
से एक बहुत अच्छा उदाहरण मिला । ToolTipPopup क्लास एक साधारण विजेट क्लास के अलावा और कुछ भी नहीं है जो एंकर व्यू के ऊपर टूलटिप दिखाता है। मैंने एक स्क्रीनशॉट कैप्चर किया।
कक्षा वास्तव में सरल है (लगभग 200 लाइनें) और देखने के योग्य है। उस वर्ग में, WeakReference
एंकर दृश्य के संदर्भ को रखने के लिए क्लास का उपयोग किया जाता है, जो सही अर्थों में बनाता है, क्योंकि एंकर व्यू को कचरा एकत्र करने के लिए संभव बनाता है, जब टूलटिप का उदाहरण एंकर व्यू से अधिक समय तक रहता है।
हैप्पी कोडिंग! :)
मुझे WeakReference
कक्षा के एक कामकाजी उदाहरण को साझा करने दें । यह एंड्रॉइड फ्रेमवर्क विजेट से थोड़ा कोड स्निपेट है जिसे कहा जाता है AutoCompleteTextView
।
संक्षेप में, इस उदाहरण में स्मृति रिसाव को रोकने के लिए ऑब्जेक्ट को WeakReference
रखने के लिए क्लास का उपयोग किया जाता है ।View
मैं सिर्फ पॉपअपडॉटसैटऑब्जर्वर क्लास को कॉपी-एंड-पेस्ट करूंगा, जो कि एक नेस्टेड क्लास है 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
एंड्रॉइड एप्लिकेशन में काम करने के उदाहरण को भी जानना चाहता था , और मुझे इसके आधिकारिक नमूना अनुप्रयोगों में कुछ नमूने मिल सकते थे। लेकिन मैं वास्तव में उनमें से कुछ के उपयोग को समझ नहीं पाया। उदाहरण के लिए, ThreadSample और DisplayingBitmaps अनुप्रयोगों का उपयोग WeakReference
अपने कोड में, लेकिन कई परीक्षण चलाने के बाद, मुझे पता चला है कि प्राप्त () विधि देता है कभी नहीं 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
एक "canonicalized" मानचित्रण वह जगह है जहाँ आप ऑब्जेक्ट के एक उदाहरण को स्मृति में रखते हैं और अन्य सभी उस विशेष उदाहरण को पॉइंटर्स या सोमेसच तंत्र के माध्यम से देखते हैं। यह वह जगह है जहां से संदर्भ संदर्भ में मदद कर सकता है। संक्षिप्त उत्तर यह है कि 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 सेट में वस्तुओं को पुनः प्राप्त करना चाहता है तो वह ऐसा करने में सक्षम होगा। आप कैशिंग, कैटलॉगिंग आदि के लिए इस तकनीक का उपयोग कर सकते हैं, जीसी और कैशिंग की अधिक गहन चर्चा के संदर्भ के लिए नीचे देखें।
रेफरी: कचरा कलेक्टर और कमजोर संदर्भ