を使用してListView
、それらの画像に関連付けられた画像とキャプションを表示しています。インターネットから画像を取得しています。テキストが表示されている間に画像を遅延読み込みする方法はありますか? UI はブロックされず、ダウンロード時に画像が表示されますか?
画像の総数は固定されていません。
を使用してListView
、それらの画像に関連付けられた画像とキャプションを表示しています。インターネットから画像を取得しています。テキストが表示されている間に画像を遅延読み込みする方法はありますか? UI はブロックされず、ダウンロード時に画像が表示されますか?
画像の総数は固定されていません。
アプリが現在表示している画像を保持するために作成したものを次に示します。ここで使用されている「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();
}
}
画像付きのレイジー リスト(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 で画像をデコードします。また、リサイクルされたビューを正しく処理するようにしています。
オープンソースのツールであるUniversal Image Loaderをお勧めします。もともとは Fedor Vlasov のプロジェクトLazyListに基づいており、それ以来大幅に改善されています。
パフォーマンスのためのマルチスレッド、Gilles Debunne によるチュートリアル。
これは Android デベロッパー ブログからのものです。推奨されるコードは次を使用します。
AsyncTasks
.FIFO cache
.garbage collect
編集できるキャッシュ。Drawable
更新:この回答は現在、かなり効果がないことに注意してください。ガベージコレクターは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();
}
ピカソ
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 つは内部ストレージにあります。
Android 4.x 以前では、Fresco は画像を Android メモリの特別な領域に配置します。これにより、アプリケーションの実行が高速になり、恐ろしい OutOfMemoryError が発生する頻度が大幅に減少します。
高性能ローダー - ここで提案されている方法を調べた後、いくつかの変更を加えたBen のソリューションを使用しました-
ビットマップよりも drawable の方が速いことに気付いたので、代わりに drawable を使用します
SoftReference を使用するのは素晴らしいことですが、キャッシュされた画像が頻繁に削除されるようになるため、画像の参照を保持するリンク リストを追加して、事前定義されたサイズに達するまで画像が削除されないようにしました。
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;
}
}
私はこの Android Training に従いましたが、メイン UI をブロックすることなく画像をダウンロードするのに優れていると思います。また、多くの画像のキャッシュとスクロールも処理します。
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 アプリケーションで画像を表示するための強力なシステムです。
リストビューで画像を遅延読み込みする方法を説明するチュートリアルを作成しました。リサイクルと並行性の問題について詳しく説明します。また、固定スレッド プールを使用して、大量のスレッドが生成されるのを防ぎます。
私が行う方法は、スレッドを起動してバックグラウンドで画像をダウンロードし、各リスト項目のコールバックを渡すことです。画像のダウンロードが完了すると、リスト アイテムのビューを更新するコールバックが呼び出されます。
ただし、ビューをリサイクルしている場合、この方法はうまく機能しません。
新しい Android Volley Library の NetworkImageView を使用していますがcom.android.volley.toolbox.NetworkImageView
、かなりうまく機能しているようです。どうやら、これはGoogle Playやその他の新しい Google アプリケーションで使用されているものと同じビューです。間違いなくチェックする価値があります。
これは Android でよくある問題で、多くの人によってさまざまな方法で解決されています。私の意見では、私が見た中で最良の解決策はPicassoと呼ばれる比較的新しいライブラリです。ハイライトは次のとおりです。
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 開発者の間で非常に人気があると思います。この問題を解決すると主張するそのようなライブラリはたくさんありますが、そのうちのいくつかだけが問題を抱えているようです。AQueryはそのようなライブラリの 1 つですが、すべての面でほとんどのライブラリより優れており、試してみる価値があります。
ApplidiumのAndroidへの軽量SDWebImage(iOS上の優れたライブラリ)ポートであるShutterbugをご覧ください。非同期キャッシュをサポートし、失敗したURLを保存し、同時実行性を適切に処理し、役立つサブクラスが含まれています。
プルリクエスト(およびバグレポート)も大歓迎です!
DroidPartsにはImageFetcherがあり、開始するための構成は不要です。
例として、DroidPartsGramのクローンを作成します。
画像の遅延読み込みに使用するライブラリについて迷っている人のための簡単なヒント:
基本的な方法は4つあります。
DIY =>最善の解決策ではありませんが、いくつかの画像の場合や、他のライブラリを使用する手間をかけずに行きたい場合
Volley の Lazy Loading ライブラリ => Android の皆さんから。それは素晴らしく、すべてですが、文書化が不十分であるため、使用するのに問題があります.
Picasso: うまく機能するシンプルなソリューションです。取り込む画像サイズを正確に指定することもできます。使い方は非常に簡単ですが、膨大な量の画像を処理する必要があるアプリでは、あまり「パフォーマンス」が高くない可能性があります。
UIL: 画像を遅延ロードする最良の方法。画像をキャッシュし(もちろん許可が必要です)、ローダーを一度初期化してから、作業を完了できます。これまでに見た中で最も成熟した非同期画像読み込みライブラリです。
Novoda には優れた遅延画像読み込みライブラリもあり、Songkick、Podio、SecretDJ、ImageSearch などの多くのアプリがそのライブラリを使用しています。
彼らのライブラリはここGithub でホストされており、かなりアクティブな課題トラッカーもあります。彼らのプロジェクトもかなり活発なようで、この返信を書いている時点で 300 件以上のコミットが行われています。
上記のすべてのコードには独自の価値がありますが、私の個人的な経験では、Picasso で試してみてください。
Picasso はこの目的専用のライブラリであり、実際にはキャッシュと他のすべてのネットワーク操作を自動的に管理します。プロジェクトにライブラリを追加し、リモート URL から画像をロードするための 1 行のコードを記述するだけです。
ここにアクセスしてください: http://code.tutsplus.com/tutorials/android-sdk-working-with-picasso--cms-22149
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;
}
}
私は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);
}
})
);
グライドは よりも優れたオプションであることがわかりましたPicasso
。私は picasso を使用して、それぞれ32
の周りのサイズの画像を読み込んでいまし200-500KB
たが、常に取得してOOM
いました。しかし、Glide
私のすべてのOOM
問題を解決しました。
いくつかの回答では、Universal Image Loader や androidimageloader などのさまざまな画像ライブラリの使用について既に言及されています。これは古い質問ですが、このようなものをまだ探している人にとっては、画像の読み込み/キャッシュ用のライブラリがいくつかあります。
それを行う別の方法は、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 配列から画像をロードします。また、メモリをリークしていないことを常に確認してください。ビットマップとドローアブルは多くの場合、メモリを大量に消費します。コードを最適化するのはあなた次第です。
Piccaso
またはなどのサードパーティのライブラリを使用してVolley
、効果的な遅延読み込みを行うことができます。以下を実装して独自に作成することもできます
URLから画像をダウンロードするコードを実装する
画像を保存および取得するためのキャッシュ機構を実装します (LruCache
キャッシュには android を使用)
更新: Kotlin コルーチンに支えられた 2020 年のソリューションを探している場合は、Coil を試してください。
Coil はCoroutine Image Loaderの頭字語です。
特徴
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 から移行することもできます
完全なドキュメントはこちら