2037

を使用してListView、それらの画像に関連付けられた画像とキャプションを表示しています。インターネットから画像を取得しています。テキストが表示されている間に画像を遅延読み込みする方法はありますか? UI はブロックされず、ダウンロード時に画像が表示されますか?

画像の総数は固定されていません。

4

41 に答える 41

1138

アプリが現在表示している画像を保持するために作成したものを次に示します。ここで使用されている「Log」オブジェクトは、Android 内の最終的な Log クラスのカスタム ラッパーであることに注意してください。

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();
    }
}
于 2009-02-18T03:56:58.083 に答える
1051

画像付きのレイジー リスト(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 のインスタンスを 1 つだけ作成し、アプリケーション全体で再利用します。このようにして、画像のキャッシュがより効率的になります。

誰かの役に立つかもしれません。バックグラウンド スレッドで画像をダウンロードします。画像は SD カードとメモリにキャッシュされています。キャッシュの実装は非常に単純で、デモには十分です。メモリ消費を減らすために、inSampleSize で画像をデコードします。また、リサイクルされたビューを正しく処理するようにしています。

代替テキスト

于 2010-06-18T08:04:09.800 に答える
565

オープンソースのツールであるUniversal Image Loaderをお勧めします。もともとは Fedor Vlasov のプロジェクトLazyListに基づいており、それ以来大幅に改善されています。

  • マルチスレッド画像の読み込み
  • ImageLoader の構成を幅広く調整する可能性 (スレッド実行プログラム、ダウンローダー、デコーダー、メモリとディスク キャッシュ、表示イメージ オプションなど)
  • メモリおよび/またはデバイスのファイル システム (または SD カード) での画像キャッシュの可能性
  • 読み込みプロセスを「聞く」可能性
  • 個別のオプションを使用してすべての表示画像呼び出しをカスタマイズする可能性
  • ウィジェットのサポート
  • Android 2.0 以降のサポート

于 2011-12-19T13:53:04.967 に答える
168

パフォーマンスのためのマルチスレッド、Gilles Debunne によるチュートリアル。

これは Android デベロッパー ブログからのものです。推奨されるコードは次を使用します。

  • AsyncTasks.
  • ハード、限られたサイズ、FIFO cache.
  • ソフトで簡単にgarbage collect編集できるキャッシュ。
  • ダウンロード中のプレースホルダー。 Drawable

ここに画像の説明を入力

于 2010-08-12T11:07:32.407 に答える
119

更新:この回答は現在、かなり効果がないことに注意してください。ガベージコレクターはSoftReferenceとWeakReferenceに積極的に作用するため、このコードは新しいアプリには適していません。(代わりに、他の回答で提案されているユニバーサルイメージローダーの ようなライブラリを試してください。)

コードを提供してくれたJamesと、SoftReferenceの使用を提案してくれたBao-Longに感謝します。JamesのコードにSoftReferenceの変更を実装しました。残念ながら、SoftReferencesにより、画像のガベージコレクションが速すぎました。私の場合、リストのサイズが制限されており、画像が小さいため、SoftReferenceがなくても問題ありませんでした。

グーグルグループのSoftReferencesに関して1年前からの議論があります:スレッドへのリンク。早すぎるガベージコレクションの解決策として、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();
}
于 2010-05-05T13:16:28.717 に答える
105

ピカソ

Jake Wharton の Picasso Library を使用します。(ActionBarSherlock の開発者による完璧な ImageLoading ライブラリ)

Android 用の強力な画像ダウンロードおよびキャッシュ ライブラリ。

画像は、Android アプリケーションに非常に必要なコンテキストと視覚的な才能を追加します。Picasso を使用すると、多くの場合 1 行のコードでアプリケーションに簡単に画像をロードできます。

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

Android での画像読み込みの一般的な落とし穴の多くは、Picasso によって自動的に処理されます。

ImageView のリサイクルとダウンロードのキャンセルをアダプターで処理します。メモリ使用量を最小限に抑えた複雑な画像変換。自動メモリおよびディスク キャッシング。

ピカソ ジェイク ウォートンの図書館

グライド

Glide は、Android 用の高速で効率的なオープンソース メディア管理フレームワークであり、メディアのデコード、メモリとディスクのキャッシュ、およびリソース プーリングをシンプルで使いやすいインターフェイスにラップします。

Glide は、ビデオ静止画、画像、およびアニメーション GIF のフェッチ、デコード、および表示をサポートしています。Glide には、開発者がほぼすべてのネットワーク スタックにプラグインできる柔軟な API が含まれています。デフォルトでは、Glide はカスタム HttpUrlConnection ベースのスタックを使用しますが、代わりに Google の Volley プロジェクトまたは Square の OkHttp ライブラリへのユーティリティ ライブラリ プラグインも含まれています。

Glide.with(this).load("your-url-here").into(imageView);

Glide の主な焦点は、あらゆる種類の画像リストのスクロールをできるだけスムーズかつ高速にすることですが、Glide は、リモート画像をフェッチ、サイズ変更、および表示する必要があるほとんどすべての場合にも効果的です。

グライド画像読み込みライブラリ

Facebookによるフレスコ

Fresco は、Android アプリケーションで画像を表示するための強力なシステムです。

画像のロードと表示は Fresco が行うため、ユーザーが行う必要はありません。ネットワーク、ローカル ストレージ、またはローカル リソースから画像を読み込み、画像が到着するまでプレースホルダーを表示します。2 レベルのキャッシュがあります。1 つはメモリに、もう 1 つは内部ストレージにあります。

フレスコGithub

Android 4.x 以前では、Fresco は画像を A​​ndroid メモリの特別な領域に配置します。これにより、アプリケーションの実行が高速になり、恐ろしい OutOfMemoryError が発生する頻度が大幅に減少します。

Fresco ドキュメンテーション

于 2014-04-04T12:35:07.650 に答える
88

高性能ローダー - ここで提案されている方法を調べた後、いくつかの変更を加えたBen のソリューションを使用しました-

  1. ビットマップよりも drawable の方が速いことに気付いたので、代わりに drawable を使用します

  2. SoftReference を使用するのは素晴らしいことですが、キャッシュされた画像が頻繁に削除されるようになるため、画像の参照を保持するリンク リストを追加して、事前定義されたサイズに達するまで画像が削除されないようにしました。

  3. InputStream を開くために、Web キャッシュを使用できるようにする 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;
}
}
于 2011-10-22T16:44:05.700 に答える
82

私はこの Android Training に従いましたが、メイン UI をブロックすることなく画像をダウンロードするのに優れていると思います。また、多くの画像のキャッシュとスクロールも処理します。

于 2012-12-27T23:27:16.260 に答える
72

1. Picassoを使用すると、多くの場合 1 行のコードでアプリケーションに簡単に画像をロードできます。

Gradle を使用します。

implementation 'com.squareup.picasso:picasso:(insert latest version)'

コードはたったの1行!

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

2. Glideスムーズなスクロールに重点を置いた Android 用の画像読み込みおよびキャッシュ ライブラリ

Gradle を使用します。

repositories {
  mavenCentral() 
  google()
}

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

// 単純なビューの場合:

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

3. fresco は Android アプリケーションで画像を表示するための強力なシステムです。

Fresco の使用を開始する

于 2014-05-22T06:00:49.807 に答える
56

リストビューで画像を遅延読み込みする方法を説明するチュートリアルを作成しました。リサイクルと並行性の問題について詳しく説明します。また、固定スレッド プールを使用して、大量のスレッドが生成されるのを防ぎます。

Listview チュートリアルでの画像の遅延読み込み

于 2011-08-27T12:54:34.627 に答える
46

私が行う方法は、スレッドを起動してバックグラウンドで画像をダウンロードし、各リスト項目のコールバックを渡すことです。画像のダウンロードが完了すると、リスト アイテムのビューを更新するコールバックが呼び出されます。

ただし、ビューをリサイクルしている場合、この方法はうまく機能しません。

于 2009-02-12T20:07:14.413 に答える
33

新しい Android Volley Library の NetworkImageView を使用していますがcom.android.volley.toolbox.NetworkImageView、かなりうまく機能しているようです。どうやら、これはGoogle Playや​​その他の新しい Google アプリケーションで使用されているものと同じビューです。間違いなくチェックする価値があります。

于 2013-06-13T15:17:05.790 に答える
33

これは Android でよくある問題で、多くの人によってさまざまな方法で解決されています。私の意見では、私が見た中で最良の解決策はPicassoと呼ばれる比較的新しいライブラリです。ハイライトは次のとおりです。

  • Jake Whartonオープン ソースですが、ActionBarSherlockの名声によって率いられています。
  • 1 行のコードで、ネットワークまたはアプリのリソースから画像を非同期に読み込みます
  • 自動ListView検出
  • ディスクとメモリの自動キャッシング
  • カスタム変換を行うことができます
  • 多くの設定可能なオプション
  • 超シンプルな API
  • 頻繁に更新
于 2013-10-15T23:22:19.497 に答える
29

インターネットからの画像の読み込み時間には多くの解決策があります。ライブラリ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;
}

遅延読み込みの問題を解決する必要があります。

于 2013-02-12T07:10:14.970 に答える
27

この問題は Android 開発者の間で非常に人気があると思います。この問題を解決すると主張するそのようなライブラリはたくさんありますが、そのうちのいくつかだけが問題を抱えているようです。AQueryはそのようなライブラリの 1 つですが、すべての面でほとんどのライブラリより優れており、試してみる価値があります。

于 2012-12-11T18:33:24.047 に答える
22

ApplidiumのAndroidへの軽量SDWebImage(iOS上の優れたライブラリ)ポートであるShutterbugをご覧ください。非同期キャッシュをサポートし、失敗したURLを保存し、同時実行性を適切に処理し、役立つサブクラスが含まれています。

プルリクエスト(およびバグレポート)も大歓迎です!

于 2012-10-16T12:43:25.303 に答える
18

DroidPartsにはImageFetcherがあり、開始するための構成は不要です。

  • ディスクとメモリ内のLRU (Least Recent Used) キャッシュを使用します。
  • 画像を効率的にデコードします。
  • バックグラウンド スレッドでのビットマップの変更をサポートします。
  • シンプルなクロスフェードあり。
  • 画像の読み込み進行状況のコールバックがあります。

例として、DroidPartsGramのクローンを作成します。

ここに画像の説明を入力してください

于 2013-05-06T09:48:19.903 に答える
17

画像の遅延読み込みに使用するライブラリについて迷っている人のための簡単なヒント:

基本的な方法は4つあります。

  1. DIY =>最善の解決策ではありませんが、いくつかの画像の場合や、他のライブラリを使用する手間をかけずに行きたい場合

  2. Volley の Lazy Loading ライブラリ => Android の皆さんから。それは素晴らしく、すべてですが、文書化が不十分であるため、使用するのに問題があります.

  3. Picasso: うまく機能するシンプルなソリューションです。取り込む画像サイズを正確に指定することもできます。使い方は非常に簡単ですが、膨大な量の画像を処理する必要があるアプリでは、あまり「パフォーマンス」が高くない可能性があります。

  4. UIL: 画像を遅延ロードする最良の方法。画像をキャッシュし(もちろん許可が必要です)、ローダーを一度初期化してから、作業を完了できます。これまでに見た中で最も成熟した非同期画像読み込みライブラリです。

于 2014-08-03T12:19:55.593 に答える
17

Novoda には優れた遅延画像読み込みライブラリもあり、Songkick、Podio、SecretDJ、ImageSearch などの多くのアプリがそのライブラリを使用しています。

彼らのライブラリはここGithub でホストされており、かなりアクティブな課題トラッカーもあります。彼らのプロジェクトもかなり活発なようで、この返信を書いている時点で 300 件以上のコミットが行われています。

于 2013-01-12T11:00:25.540 に答える
12

上記のすべてのコードには独自の価値がありますが、私の個人的な経験では、Picasso で試してみてください。

Picasso はこの目的専用のライブラリであり、実際にはキャッシュと他のすべてのネットワーク操作を自動的に管理します。プロジェクトにライブラリを追加し、リモート URL から画像をロードするための 1 行のコードを記述するだけです。

ここにアクセスしてください: http://code.tutsplus.com/tutorials/android-sdk-working-with-picasso--cms-22149

于 2015-07-09T16:16:06.600 に答える
7

URLImageViewHelperは、それを行うのに役立つ素晴らしいライブラリです。

于 2014-01-27T05:33:20.013 に答える
5
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;
 }
}
于 2013-07-18T07:16:56.707 に答える
4

私はdroidQueryを使用します。URL から画像をロードするメカニズムは 2 つあります。最初の (省略形) は次のとおりです。

$.with(myView).image(url);

ArrayAdapterこれは非常に簡単にのgetView(...)メソッドに追加できます。


ロングハンド メソッドはより多くの制御を提供し、ここでは説明されていないオプション (キャッシュやコールバックなど) もありますが、出力サイズを 200px x 200px として指定する基本的な実装は次の場所にあります。

$.ajax(new AjaxOptions().url(url)
    .type("GET")
    .dataType("image")
    .imageWidth(200).imageHeight(200)
    .success(new Function() {
        @Override
        public void invoke($ droidQuery, Object... params) {
            myImageView.setImageBitmap((Bitmap) params[0]);
        }
    })
    .error(new Function() {
        @Override
        public void invoke($ droidQuery, Object... params) {
            AjaxError e = (AjaxError) params[0];
            Log.e("$", "Error " + e.status + ": " + e.error);
        }
    })
);
于 2013-08-16T20:06:30.020 に答える
4

グライドは よりも優れたオプションであることがわかりましたPicasso。私は picasso を使用して、それぞれ32の周りのサイズの画像を読み込んでいまし200-500KBたが、常に取得してOOMいました。しかし、Glide私のすべてのOOM問題を解決しました。

于 2015-12-03T06:46:15.037 に答える
3

いくつかの回答では、Universal Image Loader や androidimageloader などのさまざまな画像ライブラリの使用について既に言及されています。これは古い質問ですが、このようなものをまだ探している人にとっては、画像の読み込み/キャッシュ用のライブラリがいくつかあります。

于 2014-06-08T09:04:32.357 に答える
3

それを行う別の方法は、getView() メソッドのスレッドでアダプターを使用することです。

Thread pics_thread = new Thread(new Runnable() {
    @Override
    public void run() {
        Bitmap bitmap = getPicture(url);
        if(bitmap != null) {
            runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    holder.imageview.setImageBitmap(bitmap);            
                    adapter.notifyDataSetChanged();
                }                       
            });             
        }       
    }                       
});

pics_thread.start();

もちろん、余分な操作を避けるために常に画像をキャッシュする必要があります。画像を HashMap 配列に配置し、画像が配列に存在するかどうかを確認し、存在しない場合はスレッドを続行するか、HashMap 配列から画像をロードします。また、メモリをリークしていないことを常に確認してください。ビットマップとドローアブルは多くの場合、メモリを大量に消費します。コードを最適化するのはあなた次第です。

于 2014-06-21T08:55:34.480 に答える
3

Piccasoまたはなどのサードパーティのライブラリを使用してVolley、効果的な遅延読み込みを行うことができます。以下を実装して独自に作成することもできます

  1. URLから画像をダウンロードするコードを実装する

  2. 画像を保存および取得するためのキャッシュ機構を実装します (LruCacheキャッシュには android を使用)

于 2016-01-19T09:59:01.847 に答える
2

更新: Kotlin コルーチンに支えられた 2020 年のソリューションを探している場合は、Coil を試してください。

Coil はCoroutine Image Loaderの頭字語です。

特徴

  1. 高速: Coil は、メモリとディスクのキャッシュ、メモリ内の画像のダウンサンプリング、ビットマップの再利用、リクエストの自動一時停止/キャンセルなど、さまざまな最適化を実行します。
  2. 軽量: Coil は最大 2000 のメソッドを APK に追加します (既に OkHttp とコルーチンを使用しているアプリの場合)。これはPicassoに匹敵し、 GlideFrescoよりも大幅に少ないです。
  3. 使いやすい: Coil の API は、Kotlin の言語機能を活用してシンプルさとボイラープレートを最小限に抑えます。
  4. 最新: Coil は Kotlin ファーストであり、Coroutines、OkHttp、Okio、AndroidX Lifecycles などの最新のライブラリを使用します。

Gradle セットアップ:

コイルは で入手できますmavenCentral()

implementation("io.coil-kt:coil:1.0.0")

クイックスタート

画像を ImageView に読み込むには、読み込み拡張機能を使用します。

// URL
imageView.load("https://www.example.com/image.jpg")

// Resource
imageView.load(R.drawable.image)

// File
imageView.load(File("/path/to/image.jpg"))

またはバックグラウンド スレッドで

// Coil (suspends the current coroutine; non-blocking and thread safe)
val request = ImageRequest.Builder(context)
    .data(url)
    .size(width, height)
    .build()
val drawable = context.imageLoader.execute(request).drawable

Picasso/Glide から移行することもできます

完全なドキュメントはこちら

于 2020-11-02T16:46:24.977 に答える