3

GridViewはURLから画像をロードします。グリッドビューをスクロールすると、画像の可能性が高くなり、修正方法がわかります... imageAdapter.notifyDataSetChanged()、gridView.invalidateViews()を試しました。この問題の解決策は見つかりませんでした。

public class ImageAdapter extends BaseAdapter{

    private Context mContext;
    private LayoutInflater mInflater;   
    private ArrayList<NodeFood> listImage = new ArrayList<NodeFood>();

    public ImageAdapter(Context c, ArrayList<NodeFood> listImage){
        this.mContext = c;
        this.listImage = listImage;
    }

    public class ViewHolder{
        ImageView imageView;
        ProgressBar progress;
    }

    public int getCount() {
        return listImage.size();
    }

    public Object getItem(int arg0) {
        return arg0;
    }

    public long getItemId(int arg0) {
        return arg0;
    }

    public View getView(int arg0, View arg1, ViewGroup arg2) {
        final ViewHolder holder;
        if(arg1 == null){
            holder  = new ViewHolder();
            mInflater = LayoutInflater.from(mContext);
            arg1    =   mInflater.inflate(R.layout.layout_item_grid, null);
            holder.imageView = (ImageView)arg1.findViewById(R.id.imageItemGrid);
            holder.progress = (ProgressBar)arg1.findViewById(R.id.progressBar);
            holder.progress.getIndeterminateDrawable().setColorFilter(0xFFFF0000,android.graphics.PorterDuff.Mode.MULTIPLY);
            arg1.setTag(holder);
        }else{
            holder = (ViewHolder)arg1.getTag();
        }
        holder.imageView.setTag(arg0);
        holder.progress.setTag(arg0);
        NodeFood a = this.listImage.get(arg0);
        String URL = a.getSRC();
        task_LoadIMG bb = new task_LoadIMG(URL,holder);
        bb.execute();
        return arg1;
    }   

    public class task_LoadIMG extends AsyncTask<Void,Void,Bitmap>{
        private String url;
        private ViewHolder holder;
        public task_LoadIMG(String url, ViewHolder holder){
            this.url = url;
            this.holder = holder;
        }
        @Override
        protected Bitmap doInBackground(Void... arg0) {
            try{
                URL aURL = new URL(this.url);
                URLConnection connect = aURL.openConnection();
                connect.connect();

                InputStream is = connect.getInputStream();
                BufferedInputStream bis = new BufferedInputStream(is);
                Bitmap bm = BitmapFactory.decodeStream(bis);
                bis.close();
                is.close();
                return bm;
            }catch(IOException e){
                return null;
            }
        }

        @Override
        protected void onPostExecute(Bitmap result) {
            holder.progress.setVisibility(View.GONE);
            holder.imageView.setImageBitmap(result);
            holder.imageView.setScaleType(ScaleType.CENTER_CROP);
        }
    }
}
4

3 に答える 3

3

問題は、AsyncTask画像が表示されている時間よりも画像の読み込みに時間がかかることです。ダウンロードが完了すると、そのセルは行き来し、次の画像にリサイクルされます。

これを回避するには、セルの画像のURLをセルのtagプロパティに保存します。次に、完了時にセルのURLが同じであることを確認しますAsyncTask。同じでない場合は、その間にセルがリサイクルされているため、更新を破棄する必要があります。ここにいくつかのコードがあります:

public View getView(int arg0, View arg1, ViewGroup arg2) {
    final ViewHolder holder;
    if(arg1 == null){
        holder  = new ViewHolder();
        mInflater = LayoutInflater.from(mContext);
        arg1    =   mInflater.inflate(R.layout.layout_item_grid, null);
        holder.imageView = (ImageView)arg1.findViewById(R.id.imageItemGrid);
        holder.progress = (ProgressBar)arg1.findViewById(R.id.progressBar);
        holder.progress.getIndeterminateDrawable().setColorFilter(0xFFFF0000,android.graphics.PorterDuff.Mode.MULTIPLY);
        arg1.setTag(holder);
    }else{
        holder = (ViewHolder)arg1.getTag();
    }
    NodeFood a = this.listImage.get(arg0);
    String URL = a.getSRC();
    holder.imageView.setTag(URL);
    task_LoadIMG bb = new task_LoadIMG(URL,holder);
    bb.execute();
    return arg1;
}   

public class task_LoadIMG extends AsyncTask<Void,Void,Bitmap>{
    private String url;
    private ViewHolder holder;
    public task_LoadIMG(String url, ViewHolder holder){
        this.url = url;
        this.holder = holder;
    }
    @Override
    protected Bitmap doInBackground(Void... arg0) {
        try{
            URL aURL = new URL(this.url);
            URLConnection connect = aURL.openConnection();
            connect.connect();

            InputStream is = connect.getInputStream();
            BufferedInputStream bis = new BufferedInputStream(is);
            Bitmap bm = BitmapFactory.decodeStream(bis);
            bis.close();
            is.close();
            return bm;
        }catch(IOException e){
            return null;
        }
    }

    @Override
    protected void onPostExecute(Bitmap result) {
        if (url.equals(holder.imageView.getTag()) {
            holder.progress.setVisibility(View.GONE);
            holder.imageView.setImageBitmap(result);
            holder.imageView.setScaleType(ScaleType.CENTER_CROP);
        } else {
            // View was updated in the meantime, ignore the image
        }
    }
}

AsyncTask帯域幅/CPUサイクルを節約するために、セルがリサイクルされたらすぐにキャンセルすることも検討してください。それは読者のための練習問題として残されています。

于 2012-08-05T06:31:05.413 に答える
0

私はボレーを使用しており、すべての非同期タスク、タグを取り除くことができます...

com.android.volley.toolbox.NetworkImageViewでImageViewを再発させます

何かのようなもの:

<com.android.volley.toolbox.NetworkImageView
android:id="@+id/twitter_avatar"
android:layout_width="48dp"
android:layout_height="48dp"
android:layout_alignParentBottom="true"
android:layout_alignParentTop="true"
android:layout_marginRight="6dip"/>


private RequestQueue mRequestQueue;
private ImageLoader mImageLoader;

private LruCache<String, Bitmap> mMemoryCache;

それから:

final int memClass = ((ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE)).getMemoryClass();

    // Use 1/8th of the available memory for this memory cache.
    final int cacheSize = 1024 * 1024 * memClass / 8;
    mMemoryCache = new LruCache<String, Bitmap>(cacheSize) {

        protected int sizeOf(String key, Bitmap bitmap) {
            // The cache size will be measured in bytes rather than number of items.
            return bitmap.getByteCount();
        }

    };

    mRequestQueue = Volley.newRequestQueue(context);
    mImageLoader = new ImageLoader(mRequestQueue, new ImageLoader.ImageCache() {

        public void putBitmap(String url, Bitmap bitmap) {
            mMemoryCache.put(url, bitmap);
        }

        public Bitmap getBitmap(String url) {
            return mMemoryCache.get(url);
        }
    });

ボレーを使用する:

NetworkImageView image = (NetworkImageView) row.findViewById(R.id.ivGridViewImage);

image.setImageUrl(url, mImageLoader);
于 2014-02-21T14:40:18.713 に答える
0

私は私のと同じ問題を抱えていましたGridView。アイテムは少なく、24個しかなく、オンラインではなく携帯電話のSDカードから画像を読み込んだのですが、スクロールすると画像が飛び交うようになりました。これは、実際には1、2行しか表示されませんでした。時間。

私がしたことは単にを追加することでした、ViewHolderそしてそれは修正されました。このチュートリアルは@scompt.comと同様に実装しているようです。チュートリアルでの彼のポイントは、ViewHolderこのようにすると、ビューが再利用されるときにへの呼び出しfindViewById()が繰り返し呼び出されないということです。これが、スクロール時に画像がジャンプしなくなった理由である可能性があります。

これが同じ苦境にある他の人を助けるかどうかはわかりません。私はSOでこの問題を検索しましたが、対処したものはほとんどありませんでした。それが誰かを助けることを願っています。

私のアダプタクラスでは: PhotoGridItemは私のモデルクラスでありArrayAdapter、次のように私の拡張機能に入力されます:ArrayAdapter<PhotoGridItem>。私のコードを少し説明するだけです。

@Override
    public View getView(int position, View convertView, ViewGroup parent) {

        View row = convertView;
        final ViewHolder holder;

        if (row == null) {

            LayoutInflater inflater = ((Activity) context).getLayoutInflater();
            row = inflater.inflate(resourceId, parent, false);

            holder = new ViewHolder();
            holder.imageView = (ImageView) row.findViewById(R.id.photo_grid_view);
            // stores holder with view
            row.setTag(holder);

        } else {

            holder = (ViewHolder)convertView.getTag();
        }

        PhotoGridItem photoGridItem = getItem(position);

        if (photoGridItem != null) {
            bm = photoGridItem.getImage();
            holder.imageView.setImageBitmap(bm);

            // positioning the image in the GridView slot
            holder.imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
            holder.imageView.setLayoutParams(new LinearLayout.LayoutParams
                    (270, 270));
        }

        return row;

    }

    public class ViewHolder{
        ImageView imageView;
    }
于 2015-03-23T00:07:15.540 に答える