追加読み込み - android 無限スクロール




ListViewでの画像の遅延読み込み (20)

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

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


Android向けのAppliediumの軽量SDWebImage(iOS上の素敵なライブラリ) Shutterbug見てみましょう。 非同期キャッシングをサポートし、失敗したURLを格納し、同時実行性をうまく処理し、有用なサブクラスが含まれています。

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


android-developers.blogspot.com/2010/07/… 、Gilles Debunneのチュートリアル。

これはAndroid Developers Blogからのものです。 推奨されるコードでは、

  • AsyncTasks
  • ハードな、限られたサイズのFIFO cache
  • 柔らかく、簡単にgarbage collectキャッシュ。
  • ダウンロード中のプレースホルダー Drawable


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


XMLアダプタをもう1つ追加したいだけです。 それはGoogleによって使用されているので、OutOfMemoryエラーを回避するために同じロジックを使用しています。

基本的にこのImageDownloaderはあなたの答えです(ほとんどの要件をカバーしています)。 あなたはそれで実装することもできます。


ピカソ

Jake WhartonのPicasso Libraryを使用してください。 (完全なImageLoadingライブラリはActionBarSherlockの開発者を構成します)

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

画像は、Androidアプリケーションに非常に必要なコンテキストと視覚的感覚を追加します。 Picassoでは、アプリケーション内で手間のかからない画像を読み込むことができます。

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("http://goo.gl/h8qOq7").into(imageView);

Glideの主な焦点は、あらゆる種類の画像のスクロールを可能な限りスムーズかつ高速に行うことですが、Glideは、リモート画像を取得、サイズ変更、および表示する必要があるほとんどすべての場合にも有効です。

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

Facebookのフレスコ画

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

フレスコ画はイメージの読み込みと表示を処理するので、必要はありません。 ネットワーク、ローカルストレージ、ローカルリソースからイメージをロードし、イメージが到着するまでプレースホルダを表示します。 それには2つのレベルのキャッシュがあります。 1つはメモリに、もう1つは内部ストレージに格納されます。

フレスコ画ギター

Android 4.x以下では、FrescoはAndroidメモリの特別な領域に画像を配置します。 これにより、アプリケーションの実行時間が短縮され、恐ろしいOutOfMemoryErrorの被害が軽減されます。

Frescoドキュメント


更新:この回答は今はかなり効果がないことに注意してください。 Garbage CollectorはSoftReferenceとWeakReferenceで積極的に行動するので、このコードは新しいアプリケーションには適していません。 (代わりに、 github.com/nostra13/Android-Universal-Image-Loaderようなライブラリを他の回答で試してみてください。)

Jamesのコードのおかげで、Bao-LongはSoftReferenceを使うことを提案してくれました。 私はJamesのコードでSoftReferenceの変更を実装しました。 残念ながら、SoftReferencesは私のイメージがあまりにも早くゴミ収集されるようにしました。 私の場合は、リストのサイズが限られていて、画像が小さいので、SoftReferenceのものがなければ問題ありませんでした。

1年前から、Googleグループの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();
}

このユニバーサルローダーをお試しください。 遅延ロード時に多くのRnDを実行した後でこれを使用しています。

github.com/nostra13/Android-Universal-Image-Loader

特徴

  • マルチスレッドイメージのロード(非同期または同期)
  • ImageLoaderの設定(スレッドエグゼキュータ、ダウンローダ、デコーダ、メモリとディスクキャッシュ、表示イメージオプションなど)の幅広いカスタマイズ
  • すべてのディスプレイイメージコール(スタブイメージ、キャッシングスイッチ、デコードオプション、ビットマップの処理と表示など)のための多くのカスタマイズオプション
  • メモリおよび/またはディスク(デバイスのファイルシステムまたはSDカード)でのイメージキャッシュ
  • リッスンロードプロセス(ダウンロードの進行状況を含む)

Android 2.0以上のサポート


これは多くの人々が多くの方法で解決しているAndroidの一般的な問題です。 私の見解では、 Picassoと呼ばれる比較的新しいライブラリが私が見てきた最高のソリューションです。 ハイライトは次のとおりです。

  • オープンソースだが、 ActionBarSherlock名声のJake Whartonが率いる。
  • 1行のコードでネットワークリソースやアプリリソースから非同期に画像を読み込む
  • 自動ListView検出
  • ディスクとメモリの自動キャッシュ
  • カスタム変換を行うことができます
  • 多くの設定可能なオプション
  • スーパーシンプルAPI
  • 頻繁に更新される

グライドライブラリを使用します。 それは私のために働いて、あまりにも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);
}

レイジーローディングイメージのためにどのライブラリを使うべきかについて決断を下す人のためのちょっとしたヒント

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

  1. DIY =>最適な解決策ではありませんが、いくつかの画像では、他のライブラリを使用するという面倒な手間を省くためには

  2. Volley's Lazy Loading library =>アンドロイドの人から。 それは素晴らしく、すべてが文書化されていないため、使用するには問題があります。

  3. Picasso:ちょうどよい単純なソリューションで、あなたが持ってきたい正確な画像サイズを指定することさえできます。使い方は非常に簡単ですが、膨大な量の画像を処理する必要のあるアプリケーションではあまり効果的ではないかもしれません。

  4. UIL:画像を読み込むのに最適な方法です。 イメージをキャッシュすることができます(もちろん許可が必要です)。ローダーを一度初期化してから、作業を完了してください。 私がこれまでに見た中で最も成熟した非同期イメージローディングライブラリです。


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

しかし、この方法は、ビューを再利用しているときはうまく機能しません。


私は、この問題はAndroid開発者の間で非常に人気があり、この問題を解決すると言っているライブラリはたくさんありますが、そのうちのほんのいくつかが目立っているようです。 AQueryはそのようなライブラリの1つですが、すべての面で大部分より優れており、試してみる価値があります。


私はこのAndroidトレーニングに従っており、メインUIをブロックせずに画像をダウンロードするのは素晴らしい仕事だと思う。 また、キャッシュを処理し、多くの画像をスクロールする処理を行います。 大量のビットマップを効率的に読み込む


私はオープンソースの機器github.com/nostra13/Android-Universal-Image-Loaderをお勧めします。 それはもともとFedor VlasovのプロジェクトLazyListに基づいており、以来大幅に改善されています。

  • マルチスレッドイメージのロード
  • ImageLoaderの設定(スレッドエグゼキュータ、ダウンローダ、デコーダ、メモリとディスクキャッシュ、表示画像オプションなど)の幅広い調整が可能
  • メモリおよび/またはデバイスのファイルsysytem(またはSDカード)上のイメージキャッシングの可能性
  • ロードプロセスを「聴く」可能性
  • 分離されたオプションですべてのディスプレイイメージコールをカスタマイズする可能性
  • ウィジェットのサポート
  • Android 2.0以上のサポート

github.com/nostra13/Android-Universal-Image-Loader


私は画像付きの怠惰なリスト (GitHubにある)の簡単なデモを作っ 。 それは誰かに役立つかもしれません。 これは、バックグラウンドスレッドでイメージをダウンロードします。 画像はSDカードとメモリにキャッシュされています。 キャッシュの実装は非常に簡単で、デモ用には十分です。 私はinSampleSizeで画像をデコードし、メモリ消費を減らしています。 リサイクルされたビューも正しく処理しようとしています。


私は魅力のように動作する別の方法をお勧めすることができます:Androidのクエリ。

そのJARファイルはhereからダウンロードできますhere

AQuery androidAQuery = new AQuery(this);

例として:

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

これは非常に高速で正確です。これを使用すると、読み込み時のアニメーション、ビットマップ(必要な場合)の取得などの多くの機能を見つけることができます。


LazyListフォークをチェックしてください。基本的には、ImageViewの呼び出しを遅らせてLazyListを改善し、2つのメソッドを作成します。

  1. あなたが "Loading image ..."のようなものを置く必要があるとき、
  2. ダウンロードした画像を表示する必要があるとき。

このオブジェクトにsingletonを実装することによってImageLoaderも改善しました。


FacebookのようなShimmerレイアウトを表示したい場合は、そのための公式facebokライブラリがあります。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:[email protected]'

これはどのように見えるかです。


与えるAndroid-Query試して。イメージを非同期にロードしてキャッシュする方法は驚くほど簡単です。


私はこの問題を抱え、lruCacheを実装しました。私は、あなたがAPI 12以上を必要とするか、または互換性v4ライブラリを使用すると信じています。lurCacheは高速なメモリですが、予算もあるので、ディスクdeveloper.android.com/training/displaying-bitmaps/…使用することができるかどうか心配している場合は、「developer.android.com/training/displaying-bitmaps/…

私は今どこからでもこのように呼び出すsingleton実装を提供します:

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

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

Web画像を取得するときに、アダプターの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);
        }
    }
}






universal-image-loader