我已经建立了一个图库,可以选择多个项目并删除。我使用自定义GridView
将图片加载到BaseAdapter
,同时删除我正在使用AsyncTask
。但是如果尝试删除多个项目,则会使数组超出绑定异常。
java.lang.IndexOutOfBoundsException: Invalid index x, size is x
at java.util.ArrayList.throwIndexOutOfBoundsException(ArrayList.java:255)
at java.util.ArrayList.get(ArrayList.java:308)
at com.android.Example.Adapters.ImageAdapter.getView(ImageAdapter.java:94)
只有当我使用AsynTask
时才会出现此错误,如果我在主线程中执行此操作,则删除工作正常。
我不知道我的ArrayList
何时出界。
这是我的自定义BaseAdapter
public class ImageAdapter extends BaseAdapter {
private com.nostra13.universalimageloader.core.ImageLoader imageLoader;
private Context mContext;
private int displayWidth;
private int imageWidth;
private ArrayList<String> f = new ArrayList<String>();// list of file paths
public ImageAdapter(Context c, ArrayList<String> f) {
mContext = c;
this.f=f;
imageLoader = ImageLoader.getInstance();
imageLoader.init(ImageLoaderConfiguration.createDefault(mContext));
DisplayMetrics metrics = new DisplayMetrics();
((Activity) c).getWindowManager().getDefaultDisplay().getMetrics(metrics);
displayWidth = metrics.widthPixels;
imageWidth=(displayWidth/3);
}
@Override
public int getCount() {
return this.f.size();
}
@Override
public Object getItem(int position) {
return this.f.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
final ImageView imageView;
if (convertView == null) {
imageView = new ImageView(mContext);
imageView.setLayoutParams(new GridView.LayoutParams(imageWidth,imageWidth));
imageView.setPadding(Utils.dpToPx(2), Utils.dpToPx(2), Utils.dpToPx(2), Utils.dpToPx(2));
imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
imageView.setCropToPadding(true);
imageView.setBackground(mContext.getResources().getDrawable(R.drawable.gridview_selector));
} else {
imageView = (ImageView) convertView;
}
//imageView.setAdjustViewBounds(true);
imageLoader.displayImage("file:///"+this.f.get(position),imageView,); //This is line number 94
return imageView;
}
}
这就是我要删除的方式。
@Override
public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
ArrayList<Uri> imageUris = new ArrayList<Uri>();
SparseBooleanArray checked = gridView.getCheckedItemPositions();
int checkedItemCount = gridView.getCheckedItemCount();
switch (item.getItemId()) {
case R.id.delete:
new DeleteAsync(checked, checkedItemCount).execute();
return true;
这是我的AsyncTask
private class DeleteAsync extends AsyncTask<Void, Void, Void> {
SparseBooleanArray _checked;
int _checkedItemCount;
private DeleteAsync(SparseBooleanArray _checked, int _checkedItemCount) {
this._checked = _checked;
this._checkedItemCount = _checkedItemCount;
}
@Override
protected Void doInBackground(Void... params) {
for (int i = (_checkedItemCount - 1); i >= 0; i--) {
if (_checked.valueAt(i)) {
File file = new File(files.get(_checked.keyAt(i)));
if (file.delete()) {
MediaScannerConnection.scanFile(getActivity(), new String[]{file.toString()}, null, null);
files.remove(_checked.keyAt(i));
} else
getActivity().runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(rootView.getContext(), getResources().getString(R.string.delete_error), Toast.LENGTH_SHORT).show();
}
});
}
}
}
@Override
protected void onPostExecute(Void void) {
super.onPostExecute(void);
imageAdapter.notifyDataSetChanged();
progress.setVisibility(View.INVISIBLE);
}
}
将adapter
设为GridView
ArrayList<String> files=getListOfImagFiles();
imageAdapter= new ImageAdapter(rootView.getContext(), files);
gridView.setAdapter(imageAdapter);
答案 0 :(得分:0)
删除前检查数组的大小。 这样的事情可能有用。
if(items.size())>0
for (int i = _checkedItemCount; i > 0; i--)
{
//do your stuff
}
答案 1 :(得分:0)
这是gridview适配器的getView中的常见问题。为了安全起见,我这样做了。
在getView()
中进行条件检查if(position<this.f.size())
{
imageLoader.displayImage("file:///"+this.f.get(position),imageView,); //This is line number 94
}
else
{
//Display some default img or error img.
}
建议:
不要根据项目的位置删除数组项。根据项目模型对象删除。
遵循MVC指南。
答案 2 :(得分:0)
目前它的问题是
因此,当你继续从文件中删除项目arraylist这行代码
imageLoader.displayImage( “文件:///” + this.f.get(位置),ImageView的,);
所以你有两个选择:
答案 3 :(得分:0)
奇怪的是,在加载图片之前,我只是安全地解决了我的问题。
if(position<getCount())
imageLoader.displayImage("file:///"+this.f.get(position),imageView,options);
我不接受我的回答,因为我认为这不是解决这个问题的完美解决方案,而且我也不知道为什么只有在我使用AsyncTask
答案 4 :(得分:0)
再次使用setAdapter而不是NotifyDataSetChanged,它将重新加载列表并且位置将是正确的。