我想将所有图片从图库加载到带有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视频第二个视频也有我之前提到的问题。任何帮助真的非常感激
答案 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);
}
}
}
}