使用asynctask将图像从库加载到gridview时,图像没有正确插入

时间:2015-03-20 12:28:02

标签: android android-asynctask

我想将所有图片从图库加载到带有asynctask的活动。我从这个link中学到了这一点。但是有一个我无法解决的问题。

当我从网格视图中慢慢向下滚动时,它可以正常工作。但是当我向上滚动或滚动得更快时,图像视图将加载以前加载的图像,然后只加载正确的照片,或者它可能随机加载几张照片,最终只能得到正确的照片。

这是我的源代码

public class PhotoPicker extends ActionBarActivity {
ArrayList<String> mArrayList = new ArrayList<String>();
ImageAdapter myImageAdapter;
AsyncTaskLoadFiles myAsyncTaskLoadFiles;
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_photo_picker);
    Context context = getApplicationContext();



    final GridView gridview = (GridView) findViewById(R.id.gridview);
    myImageAdapter = new ImageAdapter(this);
    gridview.setAdapter(myImageAdapter);

    myAsyncTaskLoadFiles = new AsyncTaskLoadFiles(myImageAdapter);
    myAsyncTaskLoadFiles.execute();

}


@Override
public boolean onCreateOptionsMenu(Menu menu) {
    // Inflate the menu; this adds items to the action bar if it is present.
    getMenuInflater().inflate(R.menu.menu_photo_picker, menu);
    return true;
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    // Handle action bar item clicks here. The action bar will
    // automatically handle clicks on the Home/Up button, so long
    // as you specify a parent activity in AndroidManifest.xml.
    int id = item.getItemId();

    //noinspection SimplifiableIfStatement
    if (id == R.id.action_settings) {
        return true;
    }

    return super.onOptionsItemSelected(item);
}



public class AsyncTaskLoadFiles extends AsyncTask<Void, String, Void> {

    ImageAdapter myTaskAdapter;
    Context context = getApplicationContext();
    Cursor cur;


    public AsyncTaskLoadFiles(ImageAdapter adapter) {
        myTaskAdapter = adapter;
    }

    @Override
    protected void onPreExecute() {
        String[] projection = new String[]{
                MediaStore.Images.Media.DATA
        };

        // Get the base URI for the People table in the Contacts content provider.
        Uri images = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;

        // Make the query.
            cur = context.getContentResolver().query(images,
                projection, // Which columns to return
                null,       // Which rows to return (all rows)
                null,       // Selection arguments (none)
                MediaStore.MediaColumns.DATE_ADDED + " DESC"        // Ordering
        );



        super.onPreExecute();
    }

    @Override
    protected Void doInBackground(Void... params) {

        if (cur.moveToFirst()) {
            String bucket;
            int bucketColumn = cur.getColumnIndex(
                    MediaStore.Images.Media.DATA);
            do {
                bucket = cur.getString(bucketColumn);
                publishProgress(bucket);
                if (isCancelled()) break;
            } while (cur.moveToNext());

        }

        return null;
    }

    @Override
    protected void onProgressUpdate(String... values) {
        myTaskAdapter.add(values[0]);
        super.onProgressUpdate(values);
    }

    @Override
    protected void onPostExecute(Void result) {
        /*myTaskAdapter.notifyDataSetChanged();*/
        super.onPostExecute(result);
    }

}

public class ImageAdapter extends BaseAdapter {
    private Context mContext;

    public ImageAdapter(Context c) {
        mContext = c;
    }

    void remove(int index){
        mArrayList.remove(index);
    }

    public void add(String path){
        mArrayList.add(path);
    }


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

    public Object getItem(int position) {
        return mArrayList.get(position);
    }

    public long getItemId(int position) {
        return 0;
    }

    class ViewHolder {
        ImageView image;
        int position;
    }

    // create a new ImageView for each item referenced by the Adapter
    public View getView(final int position, View convertView, ViewGroup parent) {
        ViewHolder holder;
        ImageView imageView;
        if (convertView == null) {
            // if it's not recycled, initialize some attributes
            imageView = new ImageView(mContext);
            imageView.setLayoutParams(new GridView.LayoutParams(230, 230));
            imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
            imageView.setPadding(2, 2, 2, 2);

            convertView = imageView;

            holder = new ViewHolder();
            holder.image = imageView;
            holder.position = position;
            convertView.setTag(holder);

        } else {
            ((ImageView)convertView).setImageBitmap(null);
            holder = (ViewHolder) convertView.getTag();
        }
        new AsyncTask<ViewHolder, Void, Bitmap>() {

            private ViewHolder v;

            @Override
            protected Bitmap doInBackground(ViewHolder... params) {

                v = params[0];
                Bitmap bm = decodeSampledBitmapFromUri(mArrayList.get(position), 220, 220);
                Log.d("holder", String.valueOf(position));
                return bm;
            }

            @Override
            protected void onPostExecute(Bitmap result) {
                super.onPostExecute(result);
                //Not work for me!
                v.image.setImageBitmap(result);





            }
        }.execute(holder);

        //imageView.setImageBitmap(bm);
        //return imageView;
        return convertView;

    }


}

public Bitmap decodeSampledBitmapFromUri(String path, int reqWidth,
                                         int reqHeight) {

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

    // Calculate inSampleSize
    options.inSampleSize = calculateInSampleSize(options, reqWidth,
            reqHeight);

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

    return bm;
}

public int calculateInSampleSize(

        BitmapFactory.Options options, int reqWidth, int reqHeight) {
    // Raw height and width of image
    final int height = options.outHeight;
    final int width = options.outWidth;
    int inSampleSize = 1;

    if (height > reqHeight || width > reqWidth) {
        if (width > height) {
            inSampleSize = Math.round((float) height
                    / (float) reqHeight);
        } else {
            inSampleSize = Math.round((float) width / (float) reqWidth);
        }
    }

    return inSampleSize;
}

}

道歉,如果我的英语让我混淆了我提供的链接有2个youtube视频第二个视频也有我之前提到的问题。任何帮助真的非常感激

1 个答案:

答案 0 :(得分:0)

这是因为GridView(ListView,RecyclerView也)重新使用已有的视图。当行视图移出屏幕时,GridView会将此视图重新用于其他数据。

在您的示例中,当您调用v.image.setImageBitmap(result);时,它可能会更改已用于其他数据项的视图中的图像。

要解决此问题,您应检查视图是否仍与数据模型相关,例如

public View getView(final int position, final View convertView, ViewGroup parent) {
    ...
    holder.image.setTag(position);
    new AsyncTask<ViewHolder, Void, Bitmap>() {
        ...
        @Override
        protected void onPostExecute(Bitmap result) {
            if(v.image.getTag() == position) {
                v.image.setImageBitmap(result);
            }
        }
    }
}