سؤال

هذا سيناريو شائع جدًا:عرض الصور في ListView والتي يجب تنزيلها من الإنترنت.

لدي الآن فئة فرعية مخصصة من ArrayAdapter والتي أستخدمها في ListView.في تطبيق getView() الخاص بي لـ ArrayAdapter، قمت بإنشاء خيط منفصل لتحميل صورة.بعد الانتهاء من التحميل، فإنه يبحث عن ImageView المناسب ويقوم بتعيين الصورة باستخدام ImageView.setImageDrawable().لذا فإن الحل الذي استخدمته يشبه إلى حد ما هذا الحل: تحميل كسول للصور في ListView

المشكلة التي أواجهها هي أنه بمجرد إجراء الاتصال بـ setImageDrawable() على ImageView، يقوم ListView بطريقة ما بتحديث جميع الصفوف المرئية حاليًا في القائمة!وينتج عن هذا نوع من الحلقة اللانهائية:

  1. يتم استدعاء getView()
  2. تم إنشاء الخيط لتحميل الصورة
  3. يتم تحميل الصورة.يتم استدعاء setImageDrawable() على ImageView
  4. يلتقطه ListView لسبب ما ويحدث نفسه
  5. لكي يتم تحديث ListView، يتم استدعاء getView() لكل صف مرئي، لذلك نعود إلى الخطوة 1 ويكرر الأمر برمته نفسه

وبقدر ما أستطيع أن أرى، فإن الحل المقترح في "Android - كيف أقوم بتحميل كسول للصور في ListView" (انظر الرابط أعلاه) ببساطة لا يعمل.قد يبدو الأمر كذلك، لكنه سيعمل ببطء شديد لأنه في الخلفية، يستمر في إعادة تحميل الصفوف المرئية حاليًا.

هل واجه أي شخص هذا من قبل و/أو لديه حل لهذا؟

هل كانت مفيدة؟

المحلول

في الحل المرتبط fetchDrawableOnThread() يجب استدعاؤه فقط إذا لم يكن العرض يحتوي بالفعل على الرسم الصحيح.

لا تحتوي طريقة العرض على رسم if getDrawable() إرجاع فارغة.

إذا كنت تقوم بإعادة استخدام الفتحات، فإنك ترى أنك بحاجة إلى المضي قدمًا وإدارة الحالة.إذا كانت عروضك تحتوي على متغير عضو يقوم بتخزين عنوان URL، وقيمة منطقية لتحديد ما إذا كان قد تم تحميله، فسيكون من السهل معرفة ما إذا كان يجب الاتصال أم لا fetchDrawableOnThread() أم لا مثلا.

أعتقد أن هذا هو الرسم toString() تفصيل المسار الذي تم تحميل الصورة منه.(إذا لم يحدث ذلك، فيمكنك إرجاع الفئة الفرعية القابلة للرسم لجعلها كذلك).في هذه الحالة، يمكنك تجنب القيمة المنطقية الموضحة أعلاه وإجراء مقارنة فقط لتحديد ما إذا كانت هي الرسومية الصحيحة أو ما إذا كنت تريد جلب بديل.

بالإضافة إلى ذلك، يجب أن يضمن getView() الخاص بك في الصف المرئي إلغاء تحميل تلك التي لم تعد مرئية، لمنع استنفاد الذاكرة.قد تكون البراعة هي نقل الصور التي لم تعد مرئية إلى مراجع إلكترونية (بحيث يتم تفريغها عند الحاجة إلى الذاكرة) كما أشار ملصق آخر في الموضوع الأصلي.

نصائح أخرى

لقد استخدمت الكود في الرابط التالي: سؤال آخر لتدفق المكدس

لقد قمت بإجراء تغييرات صغيرة من أجل حل مشكلة عرض إعادة التدوير. قمت بتعيين عنوان URL للصورة على علامة عرض الصورة في المحول.يحتوي الكود التالي على الحل الخاص بي الذي يحل مشكلة إعادة التدوير:

public void fetchDrawableOnThread(final String urlString, final ImageView imageView,Drawable drw) {

    imageView.setImageDrawable(drw);//drw is default image
    if (drawableMap.containsKey(urlString)) {
        if(imageView.getTag().toString().equals(urlString))
        {
            imageView.setImageBitmap(drawableMap.get(urlString));
            imageView.invalidate();
            return;
        }

    }

    final Handler handler = new Handler() {
        @Override
        public void handleMessage(Message message) {
            BitmapWrapper wrapper = (BitmapWrapper)message.obj;
            if(wrapper.imageurl.equals(imageView.getTag().toString()))
            {
                imageView.setImageBitmap((Bitmap)wrapper.bitmap);
                imageView.invalidate();
            }

        }
    };

    Thread thread = new Thread() {
        @Override
        public void run() {
            //TODO : set imageView to a "pending" image

            Bitmap drawable = fetchDrawable(urlString);
            BitmapWrapper wrapper = new BitmapWrapper();
            wrapper.bitmap = drawable;
            wrapper.imageurl = urlString;
            Message message = handler.obtainMessage(1, wrapper);
            handler.sendMessage(message);
        }
    };
    thread.start();
}


    public class BitmapWrapper
{
    public Bitmap bitmap;
    public String imageurl;
}

كان لي نفس القضية.

بعد ما يقرب من يومين من التصحيح/التحسين المكثف ومحاولة معرفة السبب وراء ذلك getView() يتم استدعاؤه لجميع المشاهدات مرارًا وتكرارًا عند الاستخدام setImageBitmap() على التوالي، توصلت إلى حل قذر:

1) تمديد العرف ImageView التي تستخدمها لجميع الصور في قائمتك

2) في هذا ImageView الكتابة فوق الطريقة

@Override
public void requestLayout()
{ 
  return; 
}

3) قذر ولكنه يعمل بالنسبة لي

4) الربح ;)

انا املك ThumbnailAdapter الذي يختتم هذا النمط بأكمله الذي قد يساعد.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top