AndroidでGifピクチャをロードする方法について

6905 ワード

通常AndroidのImageViewはGifピクチャをロードすることができず、何の処理もしない場合、ImageViewにロードされたGifは第1フレームのみを表示する.
ここで使われているのはグーグルが2014年のIO大会で提案したフレームワークGlideで、とても便利です.
1.Android Studioを開き、builde.gradleに追加
compile 'com.github.bumptech.glide:glide:3.6.1'
2.ロードは簡単ですので、直接コードを一言でいいです
Glide.with(this).load(R.drawable.loading).into(imageView);
   Loading  url   

しかし、数日使用すると、いくつかの問題が見つかります.
なぜ、最初にロードしたときに占位図しか表示されず、2回目に正常な画像が表示されるのでしょうか.
なぜ私はいつもYou cannot start a load for a destroyed activityのような異常を得るのですか?
どうしてロードした画像にsetTag()を付けられないのですか?
どうして?どうして?こんなNBのライブラリにこんなに多くの問題があるとは.そうですね.これが私が今日お話しするポイントです.上記の問題をどのように避けるか.
いくつかのソリューション
1.この円形Imageviewライブラリまたは他のカスタム円形Imageviewをちょうど使用して、占有スペースを設定した場合、最初の問題に直面します.どのように解決しますか?
シナリオ1:占有を設定しない;シナリオ2:GlideのTransformation APIを使用して円形Bitmapの変換をカスタマイズします.ここでは既存の例です.シナリオ3:次のコードを使用して画像をロードします.
Glide.with(mContext)
    .load(url) 
    .placeholder(R.drawable.loading_spinner)
    .into(new SimpleTarget(width, height) {
        @Override 
        public void onResourceReady(Bitmap bitmap, GlideAnimation anim) {
            // setImageBitmap(bitmap) on CircleImageView 
        } 
    };

2.2つ目の質問については、メインスレッド以外でGlideを使用して画像をロードしないで、本当に使用した場合はcontextパラメータをgetApplicationContextに変更してください.詳細はこのissueを参照してください.
3.なぜTagをセットできないのかというと、姿勢が悪いからですよ.ImageViewのTagの設定方法私の話をよく聞いてください.
シナリオ1:setTag(int,object)メソッドを使用してtagを設定し、具体的な使い方は以下の通りである.
Javaコードはソース紫です.
Glide.with(context).load(urls.get(i).getUrl()).fitCenter().into(imageViewHolder.image);
        imageViewHolder.image.setTag(R.id.image_tag, i);
        imageViewHolder.image.setOnClickListener(new View.OnClickListener() {
            @Override
                int position = (int) v.getTag(R.id.image_tag);
                Toast.makeText(context, urls.get(position).getWho(), Toast.LENGTH_SHORT).show();
            }
        });

同時にvaluesフォルダの下にidsを新規作成する.xml、追加
<item name="image_tag" type="id"/>

大成功!
シナリオ2:Glideの3.6.0以降、グローバル設定の方法が新たに追加されました.具体的な方法は以下の通りです.
GlideMoudleインタフェースを実装し、ViewTagetのtagIdをグローバルに設定します.
public class MyGlideMoudle implements GlideModule{
    @Override
    public void applyOptions(Context context, GlideBuilder builder) {
        ViewTarget.setTagId(R.id.glide_tag_id);
    }

    @Override
    public void registerComponents(Context context, Glide glide) {

    }
}

同様にidsでxmlでidを追加
<item name="glide_tag_id" type="id"/>

最後にAndroidManifestでxmlファイルに追加
<meta-data
    android:name="com.yourpackagename.MyGlideMoudle"
    android:value="GlideModule" />

また楽しく游ぶことができて、にこにこ`(∩∩)’.
シナリオ3:ImageViewTagetから継承されたクラスを書き、そのget/setRequestメソッドを複写します.
Glide.with(context).load(urls.get(i).getUrl()).fitCenter().into(new ImageViewTarget(imageViewHolder.image) {
            @Override
            protected void setResource(GlideDrawable resource) {
                imageViewHolder.image.setImageDrawable(resource);
            }

            @Override
            public void setRequest(Request request) {
                imageViewHolder.image.setTag(i);
                imageViewHolder.image.setTag(R.id.glide_tag_id,request);
            }

            @Override
            public Request getRequest() {
                return (Request) imageViewHolder.image.getTag(R.id.glide_tag_id);
            }
        });

        imageViewHolder.image.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                int position = (int) v.getTag();
                Toast.makeText(context, urls.get(position).getWho(), Toast.LENGTH_SHORT).show();
            }
        });

いくつかのテクニック
1.Glide.with(context).resumeRequests()とGlide.with(context).pauseRequests()
リストがスライドしている間にpauseRequests()キャンセル要求が呼び出され、スライドが停止している間にresumeRequests()リカバリ要求が呼び出されます.これでいいのではないでしょうか.
2.Glide.clear()
この方法は、すべてのピクチャロード要求をクリアしたい場合に役立ちます.
3.ListPreloader
リストをプリロードしたい場合は、ListPreloaderというクラスを試してみてください.