문제

나는 ListView 해당 이미지와 관련된 일부 이미지 및 캡션을 표시합니다.인터넷에서 이미지를 가져오고 있습니다.텍스트가 표시되는 동안 UI가 잠기지 않고 이미지가 다운로드될 때 표시되도록 이미지를 지연 로드하는 방법이 있습니까?

총 이미지 수는 고정되어 있지 않습니다.

도움이 되었습니까?

해결책

내 앱이 현재 표시되는 이미지를 보관하기 위해 만든 내용은 다음과 같습니다. 여기에 사용중인 "로그"객체는 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();
    }
}

다른 팁

내가 만든 게으른 목록의 간단한 데모 (Github에 위치) 이미지와 함께.

기본 사용

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 카드와 메모리에 캐시됩니다. 캐시 구현은 매우 간단하며 데모에 충분합니다. 메모리 소비를 줄이기 위해 이미지를 비 사는 이미지로 디코딩합니다. 또한 재활용 뷰를 올바르게 처리하려고합니다.

Alt text

오픈 소스 악기를 추천합니다 범용 이미지 로더. 원래 Fedor Vlasov의 프로젝트를 기반으로합니다 라자이스트 그 이후로 크게 개선되었습니다.

  • 멀티 스레드 이미지 로딩
  • 넓은 튜닝 이미지 로더 구성 가능성 (스레드 execeters, 다운로드, 디코더, 메모리 및 디스크 캐시, 디스플레이 이미지 옵션 등)
  • 메모리 및/또는 장치 파일 Sysytem (또는 SD 카드)에서 이미지 캐싱 가능성
  • 로딩 프로세스를 "듣는"가능성
  • 분리 된 옵션으로 모든 디스플레이 이미지 호출을 사용자 정의 할 가능성
  • 위젯 지원
  • Android 2.0+ 지원

성능을위한 멀티 스레딩, Gilles Debunne의 튜토리얼.

이것은 Android 개발자 블로그에서 나온 것입니다. 제안 된 코드는 다음을 사용합니다.

  • AsyncTasks.
  • 단단하고 제한된 크기, FIFO cache.
  • 부드럽고 쉽게 garbage collect-ED 캐시.
  • 자리 표시 자 Drawable 다운로드하는 동안.

enter image description here

업데이트 :이 답변은 이제 매우 효과적이지 않습니다. 쓰레기 수집가는 Softreference 및 약점에서 적극적으로 작용 하므로이 코드는 새로운 앱에 적합하지 않습니다. (대신 라이브러리를 사용해보십시오 범용 이미지 로더 다른 답변에서 제안.)

코드에 대한 James에게 감사드립니다. Softreference 사용 제안에 대해서는 Bao-Long입니다. James의 코드에서 Softreference 변경 사항을 구현했습니다. 불행히도 Softreferences는 내 이미지가 너무 빨리 쓰레기를 수집했습니다. 내 경우에는 목록 크기가 제한되고 이미지가 작기 때문에 Softreference 재료 없이는 괜찮 았습니다.

1 년 전 Google Groups의 Softreferences에 관한 토론이 있습니다. 스레드 링크. 너무 견고한 쓰레기 수집에 대한 해결책으로, 그들은 Dalvik.system.vmruntime.setminimumheapsize ()를 사용하여 VM 힙 크기를 수동으로 설정할 가능성을 제안합니다.

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

피카소

Jake Wharton의 Picasso Library를 사용하십시오. (완벽한 Imageloading 라이브러리 형태 ActionBarsherlock의 개발자)

Android 용 강력한 이미지 다운로드 및 캐싱 라이브러리.

이미지는 안드로이드 애플리케이션에 필요한 맥락과 시각적 감각을 추가합니다. Picasso는 응용 프로그램에서 번거롭지 않은 이미지로드를 허용합니다.

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

안드로이드에서 이미지 로딩의 많은 일반적인 함정은 Picasso에 의해 자동으로 처리됩니다.

ImageView 재활용 처리 및 어댑터에서 취소를 다운로드합니다. 최소한의 메모리 사용으로 복잡한 이미지 변환. 자동 메모리 및 디스크 캐싱.

피카소 제이크 와튼의 도서관

활주

Glide는 Android를위한 빠르고 효율적인 오픈 소스 미디어 관리 프레임 워크로 미디어 디코딩, 메모리 및 디스크 캐싱 및 리소스 풀링을 간단하고 사용하기 쉬운 인터페이스로 랩핑합니다.

Glide는 비디오, 디코딩 및 비디오 스틸, 이미지 및 애니메이션 GIF 표시를 지원합니다. 글라이드에는 개발자가 거의 모든 네트워크 스택에 연결할 수있는 유연한 API가 포함되어 있습니다. 기본적으로 GLIDE는 사용자 정의 HTTPURLConnection 기반 스택을 사용하지만 유틸리티 라이브러리도 Google의 Volley Project 또는 Square의 OKHTTP 라이브러리에 플러그인하는 것도 포함되어 있습니다.

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

Glide의 주요 초점은 모든 종류의 이미지 목록을 가능한 한 매끄럽고 빠르게 스크롤하는 데 있어야하지만 Glide는 원격 이미지를 가져오고 크기를 조정하고 표시 해야하는 거의 모든 경우에도 효과적입니다.

글라이드 이미지 로딩 라이브러리

Facebook의 Fresco

Fresco는 Android 응용 프로그램에 이미지를 표시하기위한 강력한 시스템입니다.

Fresco는 이미지로드 및 디스플레이를 처리하므로 필요하지 않습니다. 네트워크, 로컬 스토리지 또는 로컬 리소스에서 이미지를로드하고 이미지가 도착할 때까지 자리 표시자를 표시합니다. 두 가지 수준의 캐시가 있습니다. 하나는 메모리와 내부 스토리지에 있습니다.

프레스코 github

Android 4.X 이하에서 Fresco는 이미지를 Android 메모리의 특수 영역에 넣습니다. 이렇게하면 응용 프로그램이 더 빨리 실행되며 끔찍한 외형이 훨씬 덜 자주 발생합니다.

프레스코 문서

고성능 로더 - 여기에서 제안 된 방법을 검토 한 후 벤의 해결책 몇 가지 변경 사항이 있습니다.

  1. 나는 드로블로 작업하는 것이 비트 맵으로 더 빠르기 때문에 대신 드로우블을 사용한다는 것을 깨달았습니다.

  2. softreference를 사용하면 좋지만 캐시 된 이미지를 너무 자주 삭제하여 이미지 참조를 보유하는 링크 된 목록을 추가하여 이미지에서 삭제할 수없는 크기가 사전 정의 된 크기에 도달 할 때까지 이미지를 삭제하지 않습니다.

  3. 입력 스트림을 열기 위해 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. 피카소 응용 프로그램에서 번거롭지 않은 이미지로드가 가능합니다.

Gradle 사용 :

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

한 줄의 코드!

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

2. 활주 부드러운 스크롤에 중점을 둔 안드로이드 용 이미지 로딩 및 캐싱 라이브러리

Gradle 사용 :

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. 프레스코 Fresco는 이미지로드 및 디스플레이를 관리하므로 필요하지 않습니다.

프레스코를 시작하는 것

ListView에서 이미지를 게으른로드하는 방법을 설명하는 자습서를 작성했습니다. 나는 재활용 및 동시성 문제에 대해 자세히 설명합니다. 또한 고정 스레드 풀을 사용하여 많은 스레드가 발생하지 않도록합니다.

ListView 튜토리얼에서 이미지의 게으른로드

내가하는 방식은 스레드를 시작하여 백그라운드에서 이미지를 다운로드하고 각 목록 항목에 대한 콜백을 건네주는 것입니다. 이미지가 완료되면 다운로드가 완료되면 콜백이 호출하여 목록 항목의 뷰를 업데이트합니다.

그러나이 방법은보기를 재활용 할 때 잘 작동하지 않습니다.

좋은 예를 한 번 더 추가하고 싶습니다. XML 어댑터. Google에서 사용되며 동일한 논리를 사용하여 외부 메모리 오류를 피합니다.

원래 이 ImageNownloader 대부분의 요구 사항을 다루기 때문에 답변입니다. 일부는 또한 구현할 수 있습니다.

새로운 Android Volley Library에서 NetworkImageview를 사용하고 있습니다. com.android.volley.toolbox.NetworkImageView, 그리고 그것은 꽤 잘 작동하는 것 같습니다. 분명히 이것은 사용되는 것과 동일합니다. 구글 플레이 및 기타 새로운 Google 응용 프로그램. 확실히 체크 아웃 할 가치가 있습니다.

이것은 많은 사람들이 여러 가지 방법으로 해결 한 Android의 일반적인 문제입니다. 제 생각에 내가 본 최고의 솔루션은 비교적 새로운 도서관입니다. 피카소. 하이라이트는 다음과 같습니다.

  • 오픈 소스이지만 향했다 Jake WhartonActionBarsherLock 명성.
  • 한 줄의 코드로 네트워크 또는 앱 리소스에서 이미지를 비동기로로드
  • 자동적 인 ListView 발각
  • 자동 디스크 및 메모리 캐싱
  • 맞춤 변환을 수행 할 수 있습니다
  • 구성 가능한 많은 옵션
  • 매우 간단한 API
  • 자주 업데이트되었습니다

인터넷의 이미지 로딩 시간에는 많은 솔루션이 있습니다. 도서관을 사용할 수도 있습니다 안드로이드 쿼리. 그것은 당신에게 필요한 모든 활동을 줄 것입니다. 무엇을하고 싶은지 확인하고 라이브러리 위키 페이지를 읽으십시오. 이미지 로딩 제한을 해결하십시오.

이것은 내 코드입니다.

@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를 마친 후 이것을 사용하고 있습니다.

범용 이미지 로더

특징

  • 멀티 스레드 이미지 로딩 (비동기 또는 동기화)
  • ImageLoader 구성 (스레드 실행자, 다운로더, 디코더, 메모리 및 디스크 캐시, 디스플레이 이미지 옵션 등의 광범위한 사용자 정의)
  • 모든 디스플레이 이미지 호출에 대한 많은 사용자 정의 옵션 (스텁 이미지, 캐싱 스위치, 디코딩 옵션, 비트 맵 처리 및 표시 등)
  • 메모리 및/또는 디스크의 이미지 캐싱 (장치의 파일 시스템 또는 SD 카드)
  • 로딩 프로세스 듣기 (진행 상황 다운로드 포함)

Android 2.0+ 지원

enter image description here

살펴보십시오 셔터 버그, Applidium의 경량 SDWebimage (iOS의 멋진 라이브러리) 포트에서 Android. 비동기 캐싱을 지원하고, 상점이 실패한 URL, 동시성을 잘 처리하며 유용한 서브 클래스가 포함되어 있습니다.

풀 요청 (및 버그 보고서)도 환영합니다!

드로이드 파트 가지다 ImageFetcher 시작하려면 구성이 없습니다.

  • 디스크 및 메모리를 사용합니다 최근에 사용되었습니다 (LRU) 캐시.
  • 이미지를 효율적으로 디코딩합니다.
  • 배경 스레드에서 비트 맵 수정을 지원합니다.
  • 간단한 크로스 페이드가 있습니다.
  • 이미지 로딩 진행 진행 콜백이 있습니다.

클론 Droidpartsgram 예를 들어 :

Enter image description here

지연 로딩 이미지에 어떤 라이브러리를 사용할지 결정하지 못한 사람을 위한 간단한 팁:

기본적으로 4가지 방법이 있습니다.

  1. DIY => 최선의 해결책은 아니지만 몇 가지 이미지에 대한 것이며 다른 라이브러리를 사용하는 번거로움 없이 가고 싶은 경우

  2. Volley의 Lazy Loading 라이브러리 => android의 사람들로부터.그것은 훌륭하고 모든 것이 있지만 문서화가 부족하여 사용하기에 문제가 있습니다.

  3. 피카소:제대로 작동하는 간단한 솔루션으로 가져오려는 정확한 이미지 크기를 지정할 수도 있습니다.사용하기는 매우 간단하지만 엄청난 양의 이미지를 처리해야 하는 앱의 경우 "성능"이 좋지 않을 수 있습니다.

  4. UIL:이미지를 지연 로드하는 가장 좋은 방법입니다.이미지를 캐시하고(물론 권한이 필요함) 로더를 한 번 초기화한 다음 작업을 완료할 수 있습니다.지금까지 본 것 중 가장 성숙한 비동기 이미지 로딩 라이브러리입니다.

Novoda는 또한 훌륭합니다 게으른 이미지 로딩 라이브러리 그리고 Songkick, Podio, SecretDJ 및 ImageSearch와 같은 많은 앱이 라이브러리를 사용합니다.

그들의 도서관은 호스팅됩니다 여기 Github에서 그들은 꽤 활동적입니다 추적기 문제 또한. 그들의 프로젝트는이 답장을 작성할 때 300 명 이상의 커밋과 함께 매우 활발한 것으로 보입니다.

내 포크를 확인하십시오 라자이스트. 기본적으로 ImageView의 호출을 지연시켜 Lazylist를 향상시키고 두 가지 방법을 만듭니다.

  1. "이미지로드 ..."와 같은 것을 넣어야 할 때
  2. 다운로드 된 이미지를 표시 해야하는 경우.

또한 구현하여 ImageLoader를 개선했습니다 하나씩 일어나는 것 이 대상에서.

위의 모든 코드는 자신의 가치가 있지만 개인적인 경험으로 피카소와 함께 시도해보십시오.

피카소 이 목적을 위해 특별히 라이브러리입니다. 즉, 즉, 캐시 및 기타 모든 네트워크 작업을 자동으로 관리합니다. 프로젝트에 라이브러리를 추가하고 원격 URL에서 이미지를로드하기 위해 단일 코드 줄을 작성해야합니다.

여기를 방문하십시오 : http://code.tutsplus.com/tutorials/android-sdk-working-with-picasso-cms-22149

Facebook과 같은 반짝이는 레이아웃을 표시하려면 공식 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>

그리고 여기에 Java 코드가 있습니다.

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

Gradle 파일 에이 종속성을 추가하십시오.

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

다음은 어떻게 생겼는지입니다.Shimmer Android screenshot

글라이드 라이브러리를 사용하십시오. 그것은 나를 위해 일했고 당신의 코드에도 효과가있을 것입니다. 그것은 GIF뿐만 아니라 이미지 모두에서도 작동합니다.

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 Query처럼 매력처럼 작동하는 다른 방법을 추천 할 수 있습니다.

당신은 그것을 다운로드 할 수 있습니다 항아리 파일 여기

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 이상이 필요하거나 Corpatiblity V4 라이브러리를 사용한다고 생각합니다. Lurcache는 빠른 메모리이지만 예산도 가지고 있으므로 걱정된다면 디스크 카시를 사용할 수 있습니다 ... 모두 설명되어 있습니다. 캐싱 비트 맵.

이제 구현을 제공하겠습니다 하나씩 일어나는 것 나는 다음과 같은 곳에서 전화합니다.

//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