জাভা এবং অ্যান্ড্রয়েড বিকাশে WeakReferences কীভাবে ব্যবহার করবেন?


166

আমি 2 বছর ধরে জাভা বিকাশকারী হয়েছি।

তবে আমি আমার কোডটিতে কখনও উইক রেফারেন্স লিখিনি। আমার অ্যাপ্লিকেশনটিকে আরও দক্ষ করতে বিশেষত অ্যান্ড্রয়েড অ্যাপ্লিকেশনটিকে কীভাবে WeakReferences ব্যবহার করবেন?


সেখানে Android এর জন্য একটি পরিবর্তন হতে পারে: stackoverflow.com/questions/299659/...
Pacerier

উত্তর:


229

WeakReferenceঅ্যান্ড্রয়েডে একটি ব্যবহার করা পুরানো জাভা ব্যবহারের চেয়ে আলাদা নয়। এখানে একটি দুর্দান্ত গাইড যা একটি বিশদ ব্যাখ্যা দেয়: দুর্বল উল্লেখগুলি বোঝা

আপনার যখনই কোনও জিনিসের রেফারেন্সের প্রয়োজন হয় তখন সেটিকে ব্যবহার করার বিষয়ে আপনার চিন্তা করা উচিত, তবে আবর্জনা সংগ্রহকারী থেকে সেই বিষয়টিকে রক্ষা করার জন্য আপনি সেই উল্লেখটি চান না। একটি ক্লাসিক উদাহরণ একটি ক্যাশে যা মেমরির ব্যবহার খুব বেশি হয়ে যায় (প্রায়শই প্রয়োগ করা হয় WeakHashMap) যখন আপনি আবর্জনা সংগ্রহ করতে চান ।

চেক আউট করতে ভুলবেন হউন SoftReferenceএবং PhantomReferenceহিসাবে ভাল।

সম্পাদনা: টম এর সাথে ক্যাশে প্রয়োগের বিষয়ে কিছু উদ্বেগ প্রকাশ করেছে WeakHashMap। সমস্যাগুলি প্রকাশ করার জন্য এখানে একটি নিবন্ধ রয়েছে: WeakHashMap একটি ক্যাশে নয়!

টম ঠিক বলেছেন যে ক্যাশিংয়ের কারণে নেটবিনের দুর্বল পারফরম্যান্স সম্পর্কে অভিযোগ রয়েছেWeakHashMap

আমি এখনও মনে করি এটির WeakHashMapসাথে ক্যাশে প্রয়োগ করা এবং এর সাথে প্রয়োগ করা আপনার নিজের হাতে রোল করা ক্যাশের সাথে তুলনা করা ভাল শিক্ষার অভিজ্ঞতা হবে SoftReference। আসল বিশ্বে আপনি সম্ভবত এই সমাধানগুলির কোনওটিই ব্যবহার করবেন না, কারণ অ্যাপাচি জেসিএসের মতো একটি তৃতীয় পক্ষের লাইব্রেরিটি ব্যবহার করা আরও তাত্পর্যপূর্ণ ।


15
না! না! না! WeakHashMapক্যাশে হিসাবে ব্যবহার করা মারাত্মক। এন্ট্রিগুলি তৈরি হওয়ার সাথে সাথে তা সরানো যেতে পারে। আপনি পরীক্ষার সময় সম্ভবত এটি ঘটবে না, তবে ব্যবহারের সময় ভাল। উল্লেখ্য, এটির মাধ্যমে নেটবিনগুলি কার্যকরভাবে 100% সিপিইউ স্টপটিতে আনা যায়।
টম হাটিন -

3
@ টম আমি আমার উত্তর আপডেট করেছি। যদিও ন্যায়সঙ্গতভাবে বলতে গেলে, আমি প্রযুক্তিগতভাবে সঠিক ছিলাম যে WeakHashMapআপনি যখন এটি পছন্দ করেন তবে এটি সঠিক পছন্দ; এমনকি যদি
ক্যাচগুলি

1
Dbyrne দ্বারা দুর্দান্ত উত্তর। এর জন্য ধন্যবাদ. খ্রিস্টের এই উত্তর গ্রহণ না করার কোনও কারণ আমি দেখতে পাচ্ছি না।
সান

@ ডিবিয়ার্ন আমি গ্রিডভিউ, ইমেজভিউ বা বেসএডাপ্টারের মতো আমার ক্রিয়াকলাপে অবজেক্টগুলি ব্যবহার করছি। অনডেট্রয়ে পদ্ধতিতে, যখন আমি ক্রিয়াকলাপটি শেষ করি, দুর্বল / সফটআরফারেন্সগুলি ব্যবহার করে এই জিনিসগুলির সাথে আমার কি কিছু করা দরকার? নাকি সিস্টেমটি স্বয়ংক্রিয়ভাবে এই বস্তুর এই স্মৃতিটিকে পরিষ্কার করে দেয়?
বেনি


64

[সম্পাদনা 2] এর আরও একটি ভাল উদাহরণ পেয়েছি WeakReferenceবিটম্যাপগুলি দক্ষতার সাথে প্রশিক্ষণের গাইড প্রদর্শনের ক্ষেত্রে ইউআই থ্রেড পৃষ্ঠাটি বিটম্যাপগুলি প্রসেসিং করা হচ্ছে এসিঙ্কটাস্কের একটি ব্যবহার দেখায় ।WeakReference

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);
            }
        }
    }
}

এটা বলে,

ইমেজভিউয়ের দুর্বল উল্লেখটি নিশ্চিত করে যে অ্যাসিঙ্কটাস্ক চিত্র চিত্র এবং এটি যে কোনও কিছু উল্লেখ করে যা আবর্জনা সংগ্রহ করা থেকে আটকাবে না । টাস্ক শেষ হওয়ার পরে ইমেজভিউ এর আশেপাশে থাকার কোনও গ্যারান্টি নেই, সুতরাং আপনাকে পোস্টে এক্সেকিউট () এ রেফারেন্সও পরীক্ষা করতে হবে। ইমেজভিউ আর থাকতে পারে না, উদাহরণস্বরূপ, ব্যবহারকারী ক্রিয়াকলাপ থেকে দূরে সরে যায় বা যদি টাস্ক শেষ হওয়ার আগে কোনও কনফিগারেশন পরিবর্তন ঘটে।

শুভ কোডিং!


[সম্পাদনা] আমি ফেসবুক-অ্যান্ড্রয়েড-এসডিকেWeakReference থেকে একটি দুর্দান্ত উদাহরণ খুঁজে পেয়েছি । টুলটিপপপআপ বর্গটি সরল উইজেট শ্রেণি ব্যতীত কিছুই নয় যা অ্যাঙ্কর দৃশ্যের উপরে সরঞ্জামটিপ দেখায়। আমি একটি স্ক্রিনশট ক্যাপচার।

স্ক্র্যাম্পটিয়াস স্ক্রিনশট

ক্লাসটি সত্যই সহজ (প্রায় 200 টি লাইন) এবং দেখার উপযুক্ত। সেই শ্রেণিতে WeakReferenceক্লাসটি অ্যাঙ্কর ভিউয়ের রেফারেন্স রাখতে ব্যবহৃত হয়, যা নিখুঁত ধারণা দেয়, কারণ অ্যাঙ্কর ভিউয়ের পক্ষে আবর্জনা সংগ্রহ করা সম্ভব হয় এমনকি যখন কোনও সরঞ্জামদণ্ড তার অ্যাঙ্কর দৃশ্যের চেয়ে দীর্ঘস্থায়ী হয়।

শুভ কোডিং! :)


আমাকে WeakReferenceক্লাসের একটি কাজের উদাহরণ ভাগ করে দিন । এটি অ্যান্ড্রয়েড ফ্রেমওয়ার্ক উইজেট থেকে প্রাপ্ত একটি ছোট কোড স্নিপেট 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অ্যান্ড্রয়েড অ্যাপ্লিকেশনটিতে কাজের উদাহরণও জানতে চেয়েছিলাম এবং এর অফিসিয়াল নমুনা অ্যাপ্লিকেশনগুলিতে আমি কিছু নমুনা খুঁজে পেতে পারি। তবে আমি তাদের কিছু ব্যবহার বুঝতে পারি নি। উদাহরণস্বরূপ, থ্রেডসাম্পল এবং প্রদর্শনবিটম্যাপ অ্যাপ্লিকেশনগুলি এর কোডটিতে ব্যবহার WeakReferenceকরে, তবে বেশ কয়েকটি পরীক্ষা চালানোর পরে আমি জানতে পেরেছি যে get () পদ্ধতিটি কখনই ফিরে আসে না null, কারণ রেফারেন্সযুক্ত ভিউ অবজেক্টটি অ্যাডাপ্টারে পুনর্ব্যবহৃত হয়, তারপরে আবর্জনা সংগ্রহ করা হয়।


1
দুর্দান্ত উদাহরণগুলির জন্য ধন্যবাদ - আমি সত্যিই অনুভব করি যে এটি প্রশ্নের প্রশ্নের গ্রহণযোগ্য উত্তর হওয়া উচিত। চিয়ার্স!
অ্যাকশায়ে সিং

@ আকশায়েসিংহ ধন্যবাদ! :)
김준호

16

অন্য কয়েকটি উত্তর অসম্পূর্ণ বা অত্যধিক দীর্ঘ বলে মনে হচ্ছে। এখানে একটি সাধারণ উত্তর।

জাভা এবং অ্যান্ড্রয়েডে কীভাবে WeakReferences ব্যবহার করবেন

আপনি নিম্নলিখিত পদক্ষেপগুলি করতে পারেন:

  1. একটি WeakReferenceপরিবর্তনশীল তৈরি করুন
  2. দুর্বল রেফারেন্স সেট করুন
  3. দুর্বল রেফারেন্স ব্যবহার করুন

কোড

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একটি দৃ strong় রেফারেন্স আছে 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);
    }
}

মন্তব্য

  • আপনার দুর্বল রেফারেন্সের কারণ হ'ল আবর্জনা সংগ্রাহক যখন আর প্রয়োজন নেই তখন জিনিসগুলি নিষ্পত্তি করতে পারেন। যদি দুটি বস্তু একে অপরের দৃ strong় রেফারেন্স ধরে রাখে তবে সেগুলি আবর্জনা সংগ্রহ করা যাবে না। এটি একটি স্মৃতি ফাঁস।
  • যদি দুটি বস্তু একে অপরের রেফারেন্সের প্রয়োজন হয় তবে অবজেক্ট এ (সাধারণত স্বল্প জীবিত অবজেক্ট) এর সাথে বি অবজেক্টের (সাধারণত দীর্ঘায়িত অবজেক্ট) দুর্বল রেফারেন্স থাকতে হবে, অন্যদিকে বি এর শক্তিশালী রেফারেন্স রয়েছে উপরের উদাহরণে, এ MyClassছিল এবং AnotherClassবি।
  • একটি ব্যবহারের বিকল্প WeakReferenceহ'ল অন্য শ্রেণিটি ইন্টারফেস প্রয়োগ করে। এটি শ্রোতা / পর্যবেক্ষক প্যাটার্নে করা হয়

ব্যবহারিক উদাহরণ


বিভ্রান্তিকর ব্যাখ্যা কি // allow MyClass to get a weak reference to this class void someMethod() { mMyClass = new MyClass(); mMyClass.someMethod(this); }??
Likejudo

@ লাইকজুডো, আপনি ঠিক বলেছেন আমি কিছু পরিবর্তনশীল এবং পদ্ধতি নামকরণ উন্নত করেছি। এখন কেমন আছে?
সুরগাচ

ফাংশন কল করার আগে না হওয়ার জন্য আপনাকে weakreferenceক্রিয়ায় বস্তুটি নিজেই পরীক্ষা doSomethingকরতে হবে । nullget
বেহরোজ.এম

7

একটি "ক্যানোনিকালাইজড" ম্যাপিং হ'ল যেখানে আপনি বস্তুর একটি উদাহরণ মেমরির মধ্যে রেখেছেন এবং অন্যরা সেই নির্দিষ্ট উদাহরণটিকে পয়েন্টার বা সামস মেকানিজমের মাধ্যমে সন্ধান করে। এখানে দুর্বল উল্লেখগুলি সহায়তা করতে পারে। সংক্ষিপ্ত উত্তরটি হ'ল WeakReferences অবজেক্টগুলি আপনার সিস্টেমে অবজেক্টের পয়েন্টার তৈরি করতে ব্যবহার করা যেতে পারে এবং এখনও অবধি আবর্জনা সংগ্রাহকরা সুযোগের বাইরে চলে গেলে তাদের পুনরায় দাবি করতে দেয় । উদাহরণস্বরূপ যদি আমার কাছে এই জাতীয় কোড থাকে:

class Registry {
     private Set registeredObjects = new HashSet();

     public void register(Object object) {
         registeredObjects.add( object );
     }
 }

আমি নিবন্ধিত যে কোনও বস্তুটি কখনই জিসি দ্বারা পুনরুদ্ধার করা হবে না কারণ সেটের সেটে এটির একটি উল্লেখ রয়েছে registeredObjects। অন্যদিকে আমি যদি এটি করি:

class Registry {
     private Set registeredObjects = new HashSet();

     public void register(Object object) {
         registeredObjects.add( new WeakReference(object) );
     }
 }

তারপরে যখন জিসি সেটে বস্তুগুলিকে পুনরায় দাবি করতে চায় তখন এটি সক্ষম হয়ে উঠবে। আপনি এই কৌশলটি ক্যাচিং, ক্যাটালগিং ইত্যাদির জন্য ব্যবহার করতে পারেন জিসি এবং ক্যাচিংয়ের আরও গভীরতর আলোচনার জন্য নীচে দেখুন।

রেফ: জঞ্জাল সংগ্রহকারী এবং দুর্বল রেফারেন্স

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.