سؤال

أنا أستخدم ListView لعرض بعض الصور والتعليقات التوضيحية المرتبطة بتلك الصور. أحصل على الصور من الإنترنت. هل هناك طريقة للحمل كسول الصور حتى أثناء عرض النص، لا يتم إغلاق واجهة المستخدم ويتم عرض الصور كما يتم تنزيلها؟

إجمالي عدد الصور غير ثابت.

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

المحلول

إليك ما قمت بإنشائه لعقد الصور التي يعرضها تطبيقي حاليا. يرجى ملاحظة أن كائن "السجل" المستخدمة هنا هو مجمع مخصص حول فئة السجل النهائي داخل Android.

package com.wilson.android.library;

/*
 Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements.  See the NOTICE file
distributed with this work for additional information
regarding copyright ownership.  The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License.  You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied.  See the License for the
specific language governing permissions and limitations
under the License.
*/
import java.io.IOException;

public class DrawableManager {
    private final Map<String, Drawable> drawableMap;

    public DrawableManager() {
        drawableMap = new HashMap<String, Drawable>();
    }

    public Drawable fetchDrawable(String urlString) {
        if (drawableMap.containsKey(urlString)) {
            return drawableMap.get(urlString);
        }

        Log.d(this.getClass().getSimpleName(), "image url:" + urlString);
        try {
            InputStream is = fetch(urlString);
            Drawable drawable = Drawable.createFromStream(is, "src");


            if (drawable != null) {
                drawableMap.put(urlString, drawable);
                Log.d(this.getClass().getSimpleName(), "got a thumbnail drawable: " + drawable.getBounds() + ", "
                        + drawable.getIntrinsicHeight() + "," + drawable.getIntrinsicWidth() + ", "
                        + drawable.getMinimumHeight() + "," + drawable.getMinimumWidth());
            } else {
              Log.w(this.getClass().getSimpleName(), "could not get thumbnail");
            }

            return drawable;
        } catch (MalformedURLException e) {
            Log.e(this.getClass().getSimpleName(), "fetchDrawable failed", e);
            return null;
        } catch (IOException e) {
            Log.e(this.getClass().getSimpleName(), "fetchDrawable failed", e);
            return null;
        }
    }

    public void fetchDrawableOnThread(final String urlString, final ImageView imageView) {
        if (drawableMap.containsKey(urlString)) {
            imageView.setImageDrawable(drawableMap.get(urlString));
        }

        final Handler handler = new Handler() {
            @Override
            public void handleMessage(Message message) {
                imageView.setImageDrawable((Drawable) message.obj);
            }
        };

        Thread thread = new Thread() {
            @Override
            public void run() {
                //TODO : set imageView to a "pending" image
                Drawable drawable = fetchDrawable(urlString);
                Message message = handler.obtainMessage(1, drawable);
                handler.sendMessage(message);
            }
        };
        thread.start();
    }

    private InputStream fetch(String urlString) throws MalformedURLException, IOException {
        DefaultHttpClient httpClient = new DefaultHttpClient();
        HttpGet request = new HttpGet(urlString);
        HttpResponse response = httpClient.execute(request);
        return response.getEntity().getContent();
    }
}

نصائح أخرى

لقد صنعت عرض تجريبي بسيط لقائمة كسول (تقع في جيثب) مع الصور.

الاستخدام الأساسي

ImageLoader imageLoader=new ImageLoader(context); ...
imageLoader.DisplayImage(url, imageView); 

لا تنس أن تضيف الأذونات التالية إلى Androidmanifest.xml:

 <uses-permission android:name="android.permission.INTERNET"/>
 <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> Please

قم بإنشاء مثيل واحد فقط من ImageLoader وإعادة استخدامه في جميع أنحاء التطبيق الخاص بك. وبهذه الطريقة، سيكون التخزين المؤقت للصور أكثر كفاءة.

قد يكون من المفيد لشخص ما. يقوم بتنزيل الصور في خيط الخلفية. يتم التخزين المؤقت الصور على بطاقة SD وفي الذاكرة. تطبيق ذاكرة التخزين المؤقت بسيط للغاية وهو ما يكفي للتوظاهر. أنا فك شفرة الصور مع insamizing للحد من استهلاك الذاكرة. أحاول أيضا التعامل مع المشاهدات المعاد تدويرها بشكل صحيح.

Alt text

أوصي صك مفتوح المصدر تحميل الصور العالمي. وبعد إنه يعتمد أصلا على مشروع فيدور فلاسوف lazylist. وقد تم تحسينه بشكل كبير منذ ذلك الحين.

  • تحميل مبادلة تحميل الصور
  • إمكانية تكوين ضبط Outheloader
  • إمكانية التخزين المؤقت للصور في الذاكرة و / أو على ملف Sysytem (أو بطاقة SD)
  • إمكانية "الاستماع" عملية التحميل
  • إمكانية تخصيص كل مكالمة صورة عرض مع خيارات مفصولة
  • دعم القطعة
  • دعم Android 2.0+.

متعددة المؤشرات للأداء, ، برنامج تعليمي جيل دي ديبونن.

هذا من مدونة مطوري Android. يستخدم الرمز المقترح:

  • AsyncTasks.
  • حجم صلب محدود، FIFO cache.
  • لينة، بسهولة garbage collectمخبأ مخبأ.
  • أ العنصر النائب Drawable أثناء التنزيل.

enter image description here

تحديث: لاحظ أن هذه الإجابة غير فعالة الآن. يتصرف جامع القمامة بقوة على Softreference and Diffection، لذلك هذا الرمز غير مناسب للتطبيقات الجديدة. (بدلا من ذلك، جرب المكتبات تحميل الصور العالمي اقترح في إجابات أخرى.)

بفضل جيمس للحصول على الكود، وباو لفترة طويلة لاقتراح استخدام Softreference. قمت بتنفيذ تغييرات Softreference على رمز James '. لسوء الحظ، تسببت softreferences في صورتي التي تم جمعها بسرعة كبيرة. في حالتي كانت على ما يرام دون الاشياء Softreence، لأن حجم القائمة محدودة وصوري صغيرة.

هناك مناقشة منذ عام فيما يتعلق بأخطيبات مجموعات Google: رابط إلى الخيط. وبعد كحل لجمع القمامة المبكرة للغاية، يقترحون إمكانية تحديد حجم كومة VM يدويا باستخدام Dalvik.system.vmruntime.setminimimheapsize ()، وهذا ليس جذابا للغاية بالنسبة لي.

public DrawableManager() {
    drawableMap = new HashMap<String, SoftReference<Drawable>>();
}

public Drawable fetchDrawable(String urlString) {
    SoftReference<Drawable> drawableRef = drawableMap.get(urlString);
    if (drawableRef != null) {
        Drawable drawable = drawableRef.get();
        if (drawable != null)
            return drawable;
        // Reference has expired so remove the key from drawableMap
        drawableMap.remove(urlString);
    }

    if (Constants.LOGGING) Log.d(this.getClass().getSimpleName(), "image url:" + urlString);
    try {
        InputStream is = fetch(urlString);
        Drawable drawable = Drawable.createFromStream(is, "src");
        drawableRef = new SoftReference<Drawable>(drawable);
        drawableMap.put(urlString, drawableRef);
        if (Constants.LOGGING) Log.d(this.getClass().getSimpleName(), "got a thumbnail drawable: " + drawable.getBounds() + ", "
                + drawable.getIntrinsicHeight() + "," + drawable.getIntrinsicWidth() + ", "
                + drawable.getMinimumHeight() + "," + drawable.getMinimumWidth());
        return drawableRef.get();
    } catch (MalformedURLException e) {
        if (Constants.LOGGING) Log.e(this.getClass().getSimpleName(), "fetchDrawable failed", e);
        return null;
    } catch (IOException e) {
        if (Constants.LOGGING) Log.e(this.getClass().getSimpleName(), "fetchDrawable failed", e);
        return null;
    }
}

public void fetchDrawableOnThread(final String urlString, final ImageView imageView) {
    SoftReference<Drawable> drawableRef = drawableMap.get(urlString);
    if (drawableRef != null) {
        Drawable drawable = drawableRef.get();
        if (drawable != null) {
            imageView.setImageDrawable(drawableRef.get());
            return;
        }
        // Reference has expired so remove the key from drawableMap
        drawableMap.remove(urlString);
    }

    final Handler handler = new Handler() {
        @Override
        public void handleMessage(Message message) {
            imageView.setImageDrawable((Drawable) message.obj);
        }
    };

    Thread thread = new Thread() {
        @Override
        public void run() {
            //TODO : set imageView to a "pending" image
            Drawable drawable = fetchDrawable(urlString);
            Message message = handler.obtainMessage(1, drawable);
            handler.sendMessage(message);
        }
    };
    thread.start();
}

رسام

استخدام جيك وارتن مكتبة بيكاسو. (مكتبة ImageLoading مثالية تشكل مطور ActionBarsherlock)

تحميل صورة قوية ومكتبة التخزين المؤقت لالروبوت.

الصور تضيف السياق والمسلق البصري الذي تمس الحاجة إليه إلى تطبيقات Android. يسمح بيكاسو بتحميل صورة خالية من المتاعب في تطبيقك - في كثير من الأحيان في سطر واحد من التعليمات البرمجية!

Picasso.with(context).load("http://i.imgur.com/DvpvklR.png").into(imageView);

تتم معالجة العديد من المزالق المشتركة من تحميل الصور على نظام Android تلقائيا بواسطة Picasso:

التعامل مع إعادة تدوير imageView وتنزيل الإلغاء في محول. تحويل الصور المعقدة مع الحد الأدنى من استخدام الذاكرة. التخزين المؤقت الذاكرة التلقائي والقرص.

مكتبة بيكاسو جيك وارتن

انسل من

يوفر Glide إطار عمل لإدارة الوسائط مفتوح المصدر بسرعة وفعالة لنظام Android الذي يلتف فك تشفير الوسائط والذاكرة والذاكرة والقرص، وتجميع الموارد في واجهة بسيطة وسهلة الاستخدام.

يدعم الإنزلاق جلب و فكيب وعرض صور الفيديو والصور والرسوم المتحركة. يتضمن الإنزلاق واجهة برمجة تطبيقات مرنة تتيح للمطورين توصيل أي مكدس شبكة تقريبا. يستخدم Glide بشكل افتراضي كومة قائمة على أجهزة HttpurLConnection مخصصة، ولكنها تتضمن أيضا توصيل مكتبات الأداة المساعدة في مشروع Google Volley أو مكتبة OKHTTP المربعة بدلا من ذلك.

Glide.with(this).load("http://goo.gl/h8qOq7").into(imageView);

يركز الإنزلاق الأساسي على جعل التمرير لأي نوع من قائمة الصور على نحو سلس وسريع قدر الإمكان، ولكن الإنزلاق فعال أيضا لأي حال من الأحوال التي تحتاج فيها إلى إحضارها وتغيير حجمها وعرضها.

مكتبة تحميل صورة Glide

فريسكو من الفيسبوك

Fresco هو نظام قوي لعرض الصور في تطبيقات Android.

فريسكو تعتني بتحميل الصور وعرضها، لذلك لا تضطر إلى ذلك. سيتم تحميل الصور من الشبكة أو التخزين المحلي أو الموارد المحلية وعرض عنصر نائب حتى تصل الصورة. لديها مستويين من ذاكرة التخزين المؤقت؛ واحد في الذاكرة وآخر في التخزين الداخلي.

فريسكو جيثب

في Android 4.x و Lower، تضع فريسكو الصور في منطقة خاصة من ذاكرة Android. يتيح هذا طلبك تشغيل أسرع - وتعاني من OutofmoreError المروع في كثير من الأحيان.

وثائق فريسكو

محمل الأداء العالي - بعد فحص الأساليب المقترحة هنا، اعتدت حل بن مع بعض التغييرات -

  1. أدركت أن العمل مع الرسمية أسرع ذلك مع الصور النقطية لذلك أستخدم الفلسلة بدلا من ذلك

  2. باستخدام Softreference رائع، لكنه يجعل الصورة المخزنة مؤقتا يتم حذفها في كثير من الأحيان، لذلك أضفت قائمة مرتبطة تحمل مراجع الصور، ومنع حذف الصورة، حتى وصلت إلى حجم محدد مسبقا

  3. لفتح Inputstream، استخدمت java.net.urlconnection التي تتيح لي استخدام ذاكرة التخزين المؤقت على الويب (تحتاج إلى تعيين ذاكرة التخزين المؤقت استجابة أولا، ولكن هذه قصة أخرى)

رمز بلدي:

import java.util.Map; 
import java.util.HashMap; 
import java.util.LinkedList; 
import java.util.Collections; 
import java.util.WeakHashMap; 
import java.lang.ref.SoftReference; 
import java.util.concurrent.Executors; 
import java.util.concurrent.ExecutorService; 
import android.graphics.drawable.Drawable;
import android.widget.ImageView;
import android.os.Handler;
import android.os.Message;
import java.io.InputStream;
import java.net.MalformedURLException; 
import java.io.IOException; 
import java.net.URL;
import java.net.URLConnection;

public class DrawableBackgroundDownloader {    

private final Map<String, SoftReference<Drawable>> mCache = new HashMap<String, SoftReference<Drawable>>();   
private final LinkedList <Drawable> mChacheController = new LinkedList <Drawable> ();
private ExecutorService mThreadPool;  
private final Map<ImageView, String> mImageViews = Collections.synchronizedMap(new WeakHashMap<ImageView, String>());  

public static int MAX_CACHE_SIZE = 80; 
public int THREAD_POOL_SIZE = 3;

/**
 * Constructor
 */
public DrawableBackgroundDownloader() {  
    mThreadPool = Executors.newFixedThreadPool(THREAD_POOL_SIZE);  
}  


/**
 * Clears all instance data and stops running threads
 */
public void Reset() {
    ExecutorService oldThreadPool = mThreadPool;
    mThreadPool = Executors.newFixedThreadPool(THREAD_POOL_SIZE);
    oldThreadPool.shutdownNow();

    mChacheController.clear();
    mCache.clear();
    mImageViews.clear();
}  

public void loadDrawable(final String url, final ImageView imageView,Drawable placeholder) {  
    mImageViews.put(imageView, url);  
    Drawable drawable = getDrawableFromCache(url);  

    // check in UI thread, so no concurrency issues  
    if (drawable != null) {  
        //Log.d(null, "Item loaded from mCache: " + url);  
        imageView.setImageDrawable(drawable);  
    } else {  
        imageView.setImageDrawable(placeholder);  
        queueJob(url, imageView, placeholder);  
    }  
} 


private Drawable getDrawableFromCache(String url) {  
    if (mCache.containsKey(url)) {  
        return mCache.get(url).get();  
    }  

    return null;  
}

private synchronized void putDrawableInCache(String url,Drawable drawable) {  
    int chacheControllerSize = mChacheController.size();
    if (chacheControllerSize > MAX_CACHE_SIZE) 
        mChacheController.subList(0, MAX_CACHE_SIZE/2).clear();

    mChacheController.addLast(drawable);
    mCache.put(url, new SoftReference<Drawable>(drawable));

}  

private void queueJob(final String url, final ImageView imageView,final Drawable placeholder) {  
    /* Create handler in UI thread. */  
    final Handler handler = new Handler() {  
        @Override  
        public void handleMessage(Message msg) {  
            String tag = mImageViews.get(imageView);  
            if (tag != null && tag.equals(url)) {
                if (imageView.isShown())
                    if (msg.obj != null) {
                        imageView.setImageDrawable((Drawable) msg.obj);  
                    } else {  
                        imageView.setImageDrawable(placeholder);  
                        //Log.d(null, "fail " + url);  
                    } 
            }  
        }  
    };  

    mThreadPool.submit(new Runnable() {  
        @Override  
        public void run() {  
            final Drawable bmp = downloadDrawable(url);
            // if the view is not visible anymore, the image will be ready for next time in cache
            if (imageView.isShown())
            {
                Message message = Message.obtain();  
                message.obj = bmp;
                //Log.d(null, "Item downloaded: " + url);  

                handler.sendMessage(message);
            }
        }  
    });  
}  



private Drawable downloadDrawable(String url) {  
    try {  
        InputStream is = getInputStream(url);

        Drawable drawable = Drawable.createFromStream(is, url);
        putDrawableInCache(url,drawable);  
        return drawable;  

    } catch (MalformedURLException e) {  
        e.printStackTrace();  
    } catch (IOException e) {  
        e.printStackTrace();  
    }  

    return null;  
}  


private InputStream getInputStream(String urlString) throws MalformedURLException, IOException {
    URL url = new URL(urlString);
    URLConnection connection;
    connection = url.openConnection();
    connection.setUseCaches(true); 
    connection.connect();
    InputStream response = connection.getInputStream();

    return response;
}
}

لقد اتبعت تدريب أندرويد هذا وأعتقد أنه يقوم بعمل ممتاز عند تنزيل الصور دون حظر UI الرئيسي. كما يتعامل مع التخزين المؤقت والتعامل مع التمرير عبر العديد من الصور: تحميل الصور النقطية الكبيرة بكفاءة

1. رسام يسمح بتحميل صورة خالية من المتاعب في تطبيقك - في كثير من الأحيان في سطر واحد من التعليمات البرمجية!

استخدام المتدرج:

implementation 'com.squareup.picasso:picasso:2.71828'

مجرد سطر واحد من التعليمات البرمجية!

Picasso.get().load("http://i.imgur.com/DvpvklR.png").into(imageView);

2. انسل من مكتبة تحميل الصور والتخزين المؤقتة لالروبوت تركز على التمرير السلس

استخدام المتدرج:

repositories {
  mavenCentral() 
  google()
}

dependencies {
   implementation 'com.github.bumptech.glide:glide:4.7.1'
   annotationProcessor 'com.github.bumptech.glide:compiler:4.7.1'
}

// للحصول على عرض بسيط:

  Glide.with(this).load("http://i.imgur.com/DvpvklR.png").into(imageView);

3. فريسكو هو نظام قوي لعرض الصور في تطبيقات Android.Fresco يعتني بتحميل الصور وعرضه، لذلك لا تضطر إلى ذلك.

البدء مع فريسكو

لقد كتبت برنامج تعليمي يشرح كيفية إجراء تحميل الصور كسول في قائمة ListView. أذهب إلى بعض التفاصيل حول قضايا إعادة التدوير والتزامن. أنا أيضا استخدام تجمع موضوع ثابت لمنع التفريخ الكثير من الخيوط.

كسول تحميل الصور في ListView تعليمي

الطريقة التي أقوم بها هي بإطلاق مؤشر ترابط لتنزيل الصور في الخلفية وتسليم رد الاتصال لكل عنصر قائمة. عند الانتهاء من تنزيل الصورة، يمكنك استدعاء رد الاتصال الذي يقوم بتحديث العرض لعنصر القائمة.

هذه الطريقة لا تعمل بشكل جيد للغاية عند إعادة تدوير المشاهدات إعادة تدويرها.

أريد فقط إضافة مثال جيد آخر، محولات XML. وبعد كما يتم استخدامها من قبل Google وأنا أيضا باستخدام نفس المنطق لتجنب خطأ OutofMemory.

في الأساس هذا imagedownloader. هل إجابتك (كما تغطي معظم الاحتياجات الخاصة بك). بعض يمكنك أيضا تطبيق ذلك أيضا.

لقد كنت أستخدم NetworkImageView من مكتبة Volley الجديدة Android com.android.volley.toolbox.NetworkImageView, ، ويبدو أن العمل جيدا. على ما يبدو، هذا هو نفس الرأي المستخدم في تطبيقات جوجل وغيرها من تطبيقات Google الجديدة. بالتأكيد يستحق التدقيق.

هذه مشكلة شائعة على نظام Android تم حلها بعدة طرق من قبل العديد من الأشخاص. في رأيي أفضل حل رأيته هو مكتبة جديدة نسبيا تسمى رسام. وبعد فيما يلي أبرز:

  • مفتوح المصدر، ولكن ترأسها Jake Wharton من ActionBarsherlock. شهرة.
  • تحميل الصور بشكل غير متزامن من موارد الشبكة أو التطبيق مع سطر واحد من التعليمات البرمجية
  • التلقائي ListView كشف
  • القرص التلقائي والذاكرة التخزين المؤقت
  • يمكن القيام بتحولات مخصصة
  • الكثير من الخيارات القابلة للتكوين
  • واجهة برمجة تطبيقية سوبر بسيطة
  • في كثير من الأحيان تحديث

حسنا، يحتوي وقت تحميل الصورة من الإنترنت على العديد من الحلول. يمكنك أيضا استخدام المكتبة android-query.. وبعد سوف يمنحك كل النشاط المطلوب. تأكد من ما تريد القيام به وقراءة صفحة Wiki المكتبة. وحل تقييد تحميل الصورة.

هذا هو رمزي:

@Override
public View getView(int position, View convertView, ViewGroup parent) {
    View v = convertView;
    if (v == null) {
        LayoutInflater vi = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        v = vi.inflate(R.layout.row, null);
    }

    ImageView imageview = (ImageView) v.findViewById(R.id.icon);
    AQuery aq = new AQuery(convertView);

    String imageUrl = "http://www.vikispot.com/z/images/vikispot/android-w.png";

    aq.id(imageview).progress(this).image(imageUrl, true, true, 0, 0, new BitmapAjaxCallback() {
        @Override
        public void callback(String url, ImageView iv, Bitmap bm, AjaxStatus status) {
            iv.setImageBitmap(bm);
        }
    ));

    return v;
}

يجب أن يحل مشكلة التحميل كسول.

أعتقد أن هذه القضية تحظى بشعبية كبيرة بين مطوري Android، وهناك الكثير من هذه المكتبات تدعي حل هذه المشكلة، ولكن يبدو أن عددا قليلا منهم في العلامة. استعلام هي واحدة من هذه المكتبة، لكنها أفضل من معظمها في جميع الجوانب وتستحق المحاولة.

يجب أن تجرب هذا التحميل العالمي هو الأفضل. أنا أستخدم هذا بعد القيام به العديد من rnd على التحميل كسول.

تحميل الصور العالمي

سمات

  • تحميل الصور multithread (ASYNC أو المزامنة)
  • تخصيص واسعة من تكوين ImageLoader (منفصول مؤشر الترابط، التنزيل، وحدة فك الترميز، ذاكرة التخزين المؤقت للذاكرة والقرص، عرض خيارات الصورة، إلخ)
  • العديد من خيارات التخصيص لكل مكالمة صورة عرض (صور كعب الروتين، مفتاح التخزين المؤقت، خيارات فك التشفير، معالجة نقطية وعرضها، إلخ)
  • التخزين المؤقت للصور في الذاكرة و / أو على القرص (نظام ملفات الجهاز أو بطاقة SD)
  • الاستماع عملية التحميل (بما في ذلك تنزيل التقدم)

دعم Android 2.0+.

enter image description here

القي نظرة على Shutterbug., ، منفذ SDWebImage خفيف الوزن في Applidium (مكتبة لطيفة على نظام iOS) إلى Android. وهو يدعم التخزين المؤقت غير المتزامن، ومخازن عناوين URL الفاشلة، ويعالج التزامن بشكل جيد، ويتم تضمين الفئات الفرعية المفيدة.

طلبات سحب (وتقارير الأخطاء) موضع ترحيب أيضا!

droidparts. لديها ImageFetcher. يتطلب ذلك التكوين الصفري للبدء.

  • يستخدم القرص والذاكرة الأقل استخدامها مؤخرا (LRU) ذاكرة التخزين المؤقت.
  • فك تشفير الصور بكفاءة.
  • يدعم تعديل الصور النقطية في خيط الخلفية.
  • لديه بسيطة عبر التلاشي.
  • لديه صورة تحميل رد الاتصال التقدم.

استنساخ droidpartsgram. مثال:

Enter image description here

مجرد نصيحة سريعة لشخص في التردد فيما يتعلق بالمكتبة لاستخدامها لصور تحميل كسول:

هناك أربع طرق أساسية.

  1. DIY => ليس الحل الأفضل ولكن لبضع صور وإذا كنت ترغب في الذهاب دون مشاحنات باستخدام المكتبات الأخرى

  2. مكتبة التحميل كسول في الطائرة => من الرجال في Android. إنه لطيف وكل شيء ولكنه موثق بشكل سيء وبالتالي هو مشكلة في الاستخدام.

  3. بيكاسو: حل بسيط يعمل فقط، يمكنك حتى تحديد حجم الصورة بالضبط الذي تريد إحضاره. من السهل الاستخدام للغاية ولكن قد لا يكون "أداء" للغاية للتطبيقات التي يجب أن تتعامل مع كميات هادئة من الصور.

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

نوفودا لديها أيضا عظيم مكتبة تحميل الصورة كسول وتستخدم العديد من التطبيقات مثل Songkick و Podio و Secretdj و AppicalSearch مكتبةها.

تم استضافة مكتبةهم هنا على جيثب ولديهم نشط جدا مشاكل المقتفي كذلك. يبدو أن مشروعهم نشطا للغاية، حيث ارتكب أكثر من 300+ في وقت كتابة هذا الرد.

تحقق بلدي شوكة lazylist.. وبعد في الأساس، أقوم بتحسين السلائيين من خلال تأخير نداء ImageView وإنشاء طريقتين:

  1. عندما تحتاج إلى وضع شيء مثل "تحميل الصورة ..."
  2. عندما تحتاج إلى إظهار الصورة التي تم تنزيلها.

أنا أيضا تحسين Imageloader عن طريق تنفيذ أ singleton. في هذا الكائن.

جميع الكود أعلاه لها قيمة خاصة بهم ولكن مع تجربتي الشخصية فقط تعطي تجربة مع بيكاسو.

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

يرجى زيارة هنا: http://code.tutsplus.com/tutorials/android-sdk-working-with-picasso--cms-22149.

إذا كنت ترغب في عرض تخطيط لامع مثل Facebook، فهناك مكتبة رسمية فيسبوك لذلك. Facebook Shimmer Android.

يعتني بكل شيء، تحتاج فقط إلى وضع رمز التصميم المرغوب الخاص بك بطريقة متداخلة في إطار لامع. هنا هو نموذج التعليمات البرمجية.

<com.facebook.shimmer.ShimmerFrameLayout
     android:id=“@+id/shimmer_view_container”
     android:layout_width=“wrap_content”
     android:layout_height="wrap_content"
     shimmer:duration="1000">

 <here will be your content to display />

</com.facebook.shimmer.ShimmerFrameLayout>

وهنا رمز جافا لذلك.

ShimmerFrameLayout shimmerContainer = (ShimmerFrameLayout) findViewById(R.id.shimmer_view_container);
shimmerContainer.startShimmerAnimation();

أضف هذا التبعية في ملف MARDLE الخاص بك.

implementation 'com.facebook.shimmer:shimmer:0.1.0@aar'

هنا كيف يبدو.Shimmer Android screenshot

استخدم مكتبة الإنزلاق. لقد عملت من أجلي وسنعمل على رمزك أيضا. يعمل لكلا الصورتين وكذلك صور متحركة أيضا.

ImageView imageView = (ImageView) findViewById(R.id.test_image); 
    GlideDrawableImageViewTarget imagePreview = new GlideDrawableImageViewTarget(imageView);
    Glide
            .with(this)
            .load(url)
            .listener(new RequestListener<String, GlideDrawable>() {
                @Override
                public boolean onException(Exception e, String model, Target<GlideDrawable> target, boolean isFirstResource) {                       
                    return false;
                }

                @Override
                public boolean onResourceReady(GlideDrawable resource, String model, Target<GlideDrawable> target, boolean isFromMemoryCache, boolean isFirstResource) {
                    return false;
                }
            })
            .into(imagePreview);
}

يمكنني أن أوصي بطريقة مختلفة تعمل مثل سحر: استعلام Android.

يمكنك تحميل ذلك إناء ملف من هنا

AQuery androidAQuery = new AQuery(this);

كمثال:

androidAQuery.id(YOUR IMAGEVIEW).image(YOUR IMAGE TO LOAD, true, true, getDeviceWidth(), ANY DEFAULT IMAGE YOU WANT TO SHOW);

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

يعطى استعلام محاولة. لديها طرق بسيطة بشكل مثير للدهشة لتحميل وصور ذاكرة التخزين المؤقت بشكل غير متزامن.

UrlimageViewHelper. هي مكتبة مذهلة تساعدك على القيام بذلك.

public class ImageDownloader {

Map<String, Bitmap> imageCache;

public ImageDownloader() {
    imageCache = new HashMap<String, Bitmap>();

}

// download function
public void download(String url, ImageView imageView) {
    if (cancelPotentialDownload(url, imageView)) {

        // Caching code right here
        String filename = String.valueOf(url.hashCode());
        File f = new File(getCacheDirectory(imageView.getContext()),
                filename);

        // Is the bitmap in our memory cache?
        Bitmap bitmap = null;

        bitmap = (Bitmap) imageCache.get(f.getPath());

        if (bitmap == null) {

            bitmap = BitmapFactory.decodeFile(f.getPath());

            if (bitmap != null) {
                imageCache.put(f.getPath(), bitmap);
            }

        }
        // No? download it
        if (bitmap == null) {
            try {
                BitmapDownloaderTask task = new BitmapDownloaderTask(
                        imageView);
                DownloadedDrawable downloadedDrawable = new DownloadedDrawable(
                        task);
                imageView.setImageDrawable(downloadedDrawable);
                task.execute(url);
            } catch (Exception e) {
                Log.e("Error==>", e.toString());
            }

        } else {
            // Yes? set the image
            imageView.setImageBitmap(bitmap);
        }
    }
}

// cancel a download (internal only)
private static boolean cancelPotentialDownload(String url,
        ImageView imageView) {
    BitmapDownloaderTask bitmapDownloaderTask = getBitmapDownloaderTask(imageView);

    if (bitmapDownloaderTask != null) {
        String bitmapUrl = bitmapDownloaderTask.url;
        if ((bitmapUrl == null) || (!bitmapUrl.equals(url))) {
            bitmapDownloaderTask.cancel(true);
        } else {
            // The same URL is already being downloaded.
            return false;
        }
    }
    return true;
}

// gets an existing download if one exists for the imageview
private static BitmapDownloaderTask getBitmapDownloaderTask(
        ImageView imageView) {
    if (imageView != null) {
        Drawable drawable = imageView.getDrawable();
        if (drawable instanceof DownloadedDrawable) {
            DownloadedDrawable downloadedDrawable = (DownloadedDrawable) drawable;
            return downloadedDrawable.getBitmapDownloaderTask();
        }
    }
    return null;
}

// our caching functions
// Find the dir to save cached images
private static File getCacheDirectory(Context context) {
    String sdState = android.os.Environment.getExternalStorageState();
    File cacheDir;

    if (sdState.equals(android.os.Environment.MEDIA_MOUNTED)) {
        File sdDir = android.os.Environment.getExternalStorageDirectory();

        // TODO : Change your diretcory here
        cacheDir = new File(sdDir, "data/ToDo/images");
    } else
        cacheDir = context.getCacheDir();

    if (!cacheDir.exists())
        cacheDir.mkdirs();
    return cacheDir;
}

private void writeFile(Bitmap bmp, File f) {
    FileOutputStream out = null;

    try {
        out = new FileOutputStream(f);
        bmp.compress(Bitmap.CompressFormat.PNG, 80, out);
    } catch (Exception e) {
        e.printStackTrace();
    } finally {
        try {
            if (out != null)
                out.close();
        } catch (Exception ex) {
        }
    }
}

// download asynctask
public class BitmapDownloaderTask extends AsyncTask<String, Void, Bitmap> {
    private String url;
    private final WeakReference<ImageView> imageViewReference;

    public BitmapDownloaderTask(ImageView imageView) {
        imageViewReference = new WeakReference<ImageView>(imageView);
    }

    @Override
    // Actual download method, run in the task thread
    protected Bitmap doInBackground(String... params) {
        // params comes from the execute() call: params[0] is the url.
        url = (String) params[0];
        return downloadBitmap(params[0]);
    }

    @Override
    // Once the image is downloaded, associates it to the imageView
    protected void onPostExecute(Bitmap bitmap) {
        if (isCancelled()) {
            bitmap = null;
        }

        if (imageViewReference != null) {
            ImageView imageView = imageViewReference.get();
            BitmapDownloaderTask bitmapDownloaderTask = getBitmapDownloaderTask(imageView);
            // Change bitmap only if this process is still associated with
            // it
            if (this == bitmapDownloaderTask) {
                imageView.setImageBitmap(bitmap);

                // cache the image

                String filename = String.valueOf(url.hashCode());
                File f = new File(
                        getCacheDirectory(imageView.getContext()), filename);

                imageCache.put(f.getPath(), bitmap);

                writeFile(bitmap, f);
            }
        }
    }

}

static class DownloadedDrawable extends ColorDrawable {
    private final WeakReference<BitmapDownloaderTask> bitmapDownloaderTaskReference;

    public DownloadedDrawable(BitmapDownloaderTask bitmapDownloaderTask) {
        super(Color.WHITE);
        bitmapDownloaderTaskReference = new WeakReference<BitmapDownloaderTask>(
                bitmapDownloaderTask);
    }

    public BitmapDownloaderTask getBitmapDownloaderTask() {
        return bitmapDownloaderTaskReference.get();
    }
}

// the actual download code
static Bitmap downloadBitmap(String url) {
    HttpParams params = new BasicHttpParams();
    params.setParameter(CoreProtocolPNames.PROTOCOL_VERSION,
            HttpVersion.HTTP_1_1);
    HttpClient client = new DefaultHttpClient(params);
    final HttpGet getRequest = new HttpGet(url);

    try {
        HttpResponse response = client.execute(getRequest);
        final int statusCode = response.getStatusLine().getStatusCode();
        if (statusCode != HttpStatus.SC_OK) {
            Log.w("ImageDownloader", "Error " + statusCode
                    + " while retrieving bitmap from " + url);
            return null;
        }

        final HttpEntity entity = response.getEntity();
        if (entity != null) {
            InputStream inputStream = null;
            try {
                inputStream = entity.getContent();
                final Bitmap bitmap = BitmapFactory
                        .decodeStream(inputStream);
                return bitmap;
            } finally {
                if (inputStream != null) {
                    inputStream.close();
                }
                entity.consumeContent();
            }
        }
    } catch (Exception e) {
        // Could provide a more explicit error message for IOException or
        // IllegalStateException
        getRequest.abort();
        Log.w("ImageDownloader", "Error while retrieving bitmap from "
                + url + e.toString());
    } finally {
        if (client != null) {
            // client.close();
        }
    }
    return null;
 }
}

كان لدي هذه المشكلة ونفذت Lrucache. أعتقد أنك بحاجة إلى API 12 فما فوق أو استخدم مكتبة V4 الموافق. Lurcache هي الذاكرة السريعة، ولكنها لديها أيضا ميزانية، لذلك إذا كنت قلقا بشأن ذلك، يمكنك استخدام DeckCache ... كلها موصوفة في التخزين المؤقت الصور النقطية.

سأقدم الآن تنفيذي الذي هو singleton. أنا أسمي من أي مكان مثل هذا:

//Where the first is a string and the other is a imageview to load.

DownloadImageTask.getInstance().loadBitmap(avatarURL, iv_avatar);

إليك الرمز المثالي لذاكرة التخزين المؤقت ثم استدعاء أعلاه في GetView عن محول عند استرداد صورة الويب:

public class DownloadImageTask {

    private LruCache<String, Bitmap> mMemoryCache;

    /* Create a singleton class to call this from multiple classes */

    private static DownloadImageTask instance = null;

    public static DownloadImageTask getInstance() {
        if (instance == null) {
            instance = new DownloadImageTask();
        }
        return instance;
    }

    //Lock the constructor from public instances
    private DownloadImageTask() {

        // Get max available VM memory, exceeding this amount will throw an
        // OutOfMemory exception. Stored in kilobytes as LruCache takes an
        // int in its constructor.
        final int maxMemory = (int) (Runtime.getRuntime().maxMemory() / 1024);

        // Use 1/8th of the available memory for this memory cache.
        final int cacheSize = maxMemory / 8;

        mMemoryCache = new LruCache<String, Bitmap>(cacheSize) {
            @Override
            protected int sizeOf(String key, Bitmap bitmap) {
                // The cache size will be measured in kilobytes rather than
                // number of items.
                return bitmap.getByteCount() / 1024;
            }
        };
    }

    public void loadBitmap(String avatarURL, ImageView imageView) {
        final String imageKey = String.valueOf(avatarURL);

        final Bitmap bitmap = getBitmapFromMemCache(imageKey);
        if (bitmap != null) {
            imageView.setImageBitmap(bitmap);
        } else {
            imageView.setImageResource(R.drawable.ic_launcher);

            new DownloadImageTaskViaWeb(imageView).execute(avatarURL);
        }
    }

    private void addBitmapToMemoryCache(String key, Bitmap bitmap) {
        if (getBitmapFromMemCache(key) == null) {
            mMemoryCache.put(key, bitmap);
        }
    }

    private Bitmap getBitmapFromMemCache(String key) {
        return mMemoryCache.get(key);
    }

    /* A background process that opens a http stream and decodes a web image. */

    class DownloadImageTaskViaWeb extends AsyncTask<String, Void, Bitmap> {
        ImageView bmImage;

        public DownloadImageTaskViaWeb(ImageView bmImage) {
            this.bmImage = bmImage;
        }

        protected Bitmap doInBackground(String... urls) {

            String urldisplay = urls[0];
            Bitmap mIcon = null;
            try {
                InputStream in = new java.net.URL(urldisplay).openStream();
                mIcon = BitmapFactory.decodeStream(in);

            } 
            catch (Exception e) {
                Log.e("Error", e.getMessage());
                e.printStackTrace();
            }

            addBitmapToMemoryCache(String.valueOf(urldisplay), mIcon);

            return mIcon;
        }

        /* After decoding we update the view on the main UI. */
        protected void onPostExecute(Bitmap result) {
            bmImage.setImageBitmap(result);
        }
    }
}
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top