簡體   English   中英

對RecyclerView的視圖的弱引用永不中斷?

[英]WeakReference to a RecyclerView's View never breaks?

我在asynctask中對recyclerview的視圖有較弱的引用(該任務會加載要在視圖中顯示的圖像)。 通常情況下(如果我使用列表視圖),當gc消失時該視圖由gc收集,因此該任務將不使用它,但就我而言(對於recyclerview),該視圖從未由gc收集,因此該任務仍具有指向視圖的弱引用,該視圖現在具有新角色(要顯示的另一幅圖像)。 我該如何解決? 我對情況的理解正確嗎?

謝謝!

我希望你明白英語不是我的母語。

編輯:這是AsyncTask的代碼:

class LoadPictureTask extends AsyncTask<String, Void, Bitmap> {
    private final WeakReference<ImageView> mImageViewReference;
    private final int mImageSize;

    LoadPictureTask(ImageView imageView, int imageSize) {
        // Use a WeakReference to ensure the ImageView can be garbage collected
        mImageViewReference = new WeakReference<>(imageView);
        mImageSize = imageSize;
    }

    @Override
    protected Bitmap doInBackground(String... params) {
        String path = params[0];
        return decodeSampledBitmapFromFile(path, mImageSize, mImageSize);
    }

    @Override
    protected void onPostExecute(Bitmap bitmap) {
        if (mImageViewReference.get() != null && bitmap != null) {
            final ImageView imageView = mImageViewReference.get();
            if (imageView != null) {
                imageView.setImageBitmap(bitmap);
            }
        }
    }
...
}

我擔心的是,在onPostExecute中,我用生成的位圖設置了另一個imageview(一個回收的位圖)

因此,我測試了上述情況,確實完全濫用了視圖的引用。 AsyncTask將圖像放置在錯誤的視圖中,並且一切都被弄亂了。 我通過從ViewHolder保存指向AsyncTask的指針來解決此問題,然后在onBindViewHolder中取消了先前執行的AsyncTask並禁用了視圖的可見性,直到新AsyncTask將其設置為可見為止。

該代碼將闡明我的意圖:

package com.teamagam.dailyselfie;

import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;

import java.util.List;

class PictureAdapter extends RecyclerView.Adapter<PictureAdapter.PictureViewHolder> {
    private LayoutInflater mInflater;
    private List<PictureInfo> mPictureInfoList;

    PictureAdapter(Context context, List<PictureInfo> pictureInfoList) {
        mInflater = LayoutInflater.from(context);
        mPictureInfoList = pictureInfoList;
    }

    @Override
    public PictureViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View view = mInflater.inflate(R.layout.layout_picture, parent, false);
        return new PictureViewHolder(view);
    }

    @Override
    public void onBindViewHolder(PictureViewHolder pictureViewHolder, int position) {
        PictureInfo pictureInfo = mPictureInfoList.get(position);
        pictureViewHolder.mTextView.setText(pictureInfo.fileName);
        int imageSize = pictureViewHolder.mImageView
                .getContext()
                .getApplicationContext()
                .getResources()
                .getInteger(R.integer.activity_main_thumbnail_size);
        if (null != pictureViewHolder.mLoadPictureTask) {
            pictureViewHolder.mLoadPictureTask.cancel(true);
        }
        pictureViewHolder.mImageView.setVisibility(View.INVISIBLE);
        pictureViewHolder.mLoadPictureTask = new LoadPictureTask(pictureViewHolder.mImageView, imageSize);
        pictureViewHolder.mLoadPictureTask.execute(pictureInfo.path);
    }

    @Override
    public int getItemCount() {
        return mPictureInfoList.size();
    }

    class PictureViewHolder extends RecyclerView.ViewHolder {
        ImageView mImageView;
        TextView mTextView;
        LoadPictureTask mLoadPictureTask;

        PictureViewHolder(View itemView) {
            super(itemView);
            mImageView = (ImageView) itemView.findViewById(R.id.ivItemListImage);
            mTextView = (TextView) itemView.findViewById(R.id.tvItemListImage);
        }
    }
}

當然還有AsyncTask的代碼:

package com.teamagam.dailyselfie;

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.BitmapFactory.Options;
import android.os.AsyncTask;
import android.view.View;
import android.widget.ImageView;

import java.lang.ref.WeakReference;

class LoadPictureTask extends AsyncTask<String, Void, Bitmap> {
    private final WeakReference<ImageView> mImageViewReference;
    private final int mImageSize;

    LoadPictureTask(ImageView imageView, int imageSize) {
        // Use a WeakReference to ensure the ImageView can be garbage collected
        mImageViewReference = new WeakReference<>(imageView);
        mImageSize = imageSize;
    }

    @Override
    protected Bitmap doInBackground(String... params) {
        String path = params[0];
        return decodeSampledBitmapFromFile(path, mImageSize, mImageSize);
    }

    @Override
    protected void onPostExecute(Bitmap bitmap) {
        if (mImageViewReference.get() != null && bitmap != null) {
            final ImageView imageView = mImageViewReference.get();
            if (imageView != null) {
                imageView.setImageBitmap(bitmap);
                imageView.setVisibility(View.VISIBLE);
            }
        }
    }

    private static Bitmap decodeSampledBitmapFromFile(String path, int requiredWidth, int requiredHeight) {

        // First decode with inJustDecodeBounds=true to check dimensions
        final Options options = new Options();
        options.inJustDecodeBounds = true;
        BitmapFactory.decodeFile(path, options);

        // Calculate inSampleSize
        options.inSampleSize = calculateSampleSize(options, requiredWidth, requiredHeight);

        // Decode bitmap with inSampleSize set
        options.inJustDecodeBounds = false;
        return BitmapFactory.decodeFile(path, options);
    }

    private static int calculateSampleSize(Options options, int requiredWidth, int requiredHeight) {
        // Raw height and width of image
        final int height = options.outHeight;
        final int width = options.outWidth;
        int sampleSize = 1;

        if (height > requiredHeight || width > requiredWidth) {

            final int halfHeight = height / 2;
            final int halfWidth = width / 2;

            // Calculate the largest sampleSize value that is a power of 2 and keeps both
            // height and width larger than the requested height and width.
            while ((halfHeight / sampleSize) >= requiredHeight
                    && (halfWidth / sampleSize) >= requiredWidth) {
                sampleSize *= 2;
            }
        }

        return sampleSize;
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM