Question

i have noticed that using the ArrayAdapter for a GridView and recycling the views i call the getView method many times and i create many view.

As you can see in my code below, i want a ArrayList of certain elements. But what happens is that due to the fact that android recycles its view i get may too many elements in the arrayList. How can i make it such that i only put in the ArrayList the exact numbers of elements (if i have 4 views i only want 4 elements)?

Thankyou

code: GridViewAdapter class

public class GridViewAdapter extends ArrayAdapter<String>  {

    private LayoutInflater inflater = null;
    private final String TAG = "GridViewAdapter";
    public Context mContext; 
    public int layoutResourceId;
    private ArrayList<String> mFilePathList = new ArrayList<String>();
    private ArrayList<ImageView> mFeatureImageCollection = new ArrayList<ImageView>();
    private ArrayList<ToggleButton> mFeatureImageButtonCollection = new ArrayList<ToggleButton>();

    public GridViewAdapter(Context context, int resource) {
        super(context, resource);
        this.mContext = context;
    }

    public GridViewAdapter(Context context, int attrs, int defStyle) {
        super(context, attrs, defStyle);

    }

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


    @Override
    public void notifyDataSetChanged() {
        // TODO Auto-generated method stub
        super.notifyDataSetChanged();
    }

    @Override
    public void remove(String object) {
        // TODO Auto-generated method stub
        super.remove(object);
    }

    @Override
    public int getCount() {
        return mFilePathList.size();
    }

    @Override
    public String getItem(int position) {
        // TODO Auto-generated method stub
        Log.w(TAG, "im in getItem");
        return mFilePathList.get(position);
    }

    @Override
    public long getItemId(int position) {
        // TODO Auto-generated method stub
        Log.i(TAG, "getItemId");
        return position;
    }


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

        GridImageView view;
        if (convertView == null) {

            inflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            view = (GridImageView) inflater.inflate(R.layout.grid_elements, null);

            view.setTag(position);
            Log.i(TAG, "VIEW TAG: "+ view.getTag());
            mFeatureImageCollection.add(view.mFeaturedImage);
            mFeatureImageButtonCollection.add(view.mFeaturedImageButton);

        } else {

            view = (GridImageView) convertView;
        }

        view.showItems(mFilePathList, position, this, mFeatureImageCollection, mFeatureImageButtonCollection);

        return view;
    }
}

code: GridViewImage

public class GridImageView  extends RelativeLayout {

    private final String TAG = "GridImageView";
    private boolean mFeaturedImageSet;
    public ImageView mAddedPhotoButton;
    public ImageView mFeaturedImage;
    public ImageView mDeleteImageButton;
    public ToggleButton mFeaturedImageButton;
    public Button btnAddPhoto;
    private boolean featureImageIsChecked = false;
    private static ArrayList<String> mFilePathList;
    private Iterator<ToggleButton> itr1;
    private Iterator<ImageView> itr2;

    public GridImageView(Context context, AttributeSet attrs) {
        super(context, attrs);      
        mFeaturedImageSet = false;
    }


    @Override
    protected void onFinishInflate() {
        super.onFinishInflate();        
        btnAddPhoto = (Button) findViewById(R.id.btnAddPhoto);
        mAddedPhotoButton = (ImageView) findViewById(R.id.ivAddedPhoto);
        mDeleteImageButton = (ImageView) findViewById(R.id.ivDeleteImageButton);
        mFeaturedImage = (ImageView) findViewById(R.id.ivFeaturedImage);        
        mFeaturedImageButton = (ToggleButton) findViewById(R.id.ivFirstPhoto);
        mFeaturedImage.setVisibility(View.INVISIBLE);       
    }

    public void showItems(final ArrayList<String> mFilePathList, final int position, 
            final GridViewAdapter myAdapter, final ArrayList<ImageView> mFeatureImageCollection, 
            final ArrayList<ToggleButton> mFeatureImageButtonCollection) {

        this.mFilePathList = mFilePathList;

        Bitmap bm = decodeSampledBitmapFromUri(mFilePathList.get(position), 95, 95);
        mAddedPhotoButton.setImageBitmap(bm);
                //invoked to delete a view/element
        mDeleteImageButton.setVisibility(View.VISIBLE);
        mDeleteImageButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                File file= new File(mFilePathList.get(position));
                if(file.exists()) {
                     file.delete();
                }
                myAdapter.remove(mFilePathList.get(position));
                mFilePathList.remove(position);
                //VendiFragment.mFilePaths.remove(position);

                myAdapter.notifyDataSetChanged();
            }
        });


        Log.i(TAG, "Position = " + Integer.toString(position));

        Log.i(TAG, "Feature Image Value = " + Boolean.toString(mFeaturedImageSet));
        if (!mFeaturedImageSet && position == 0){
            mFeaturedImage.setVisibility(View.VISIBLE);
            mFeaturedImageButton.setBackgroundResource(R.drawable.first_photo_on);
            mFeaturedImageSet = true;
        }

        //when selected it enables or disables the Feature Image from the view element
        mFeaturedImageButton.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
            public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
                Log.i(TAG, "mFeatureImageCollection.sixe(): " + mFeatureImageCollection.size());
                Log.i(TAG, "resetting al feature images to invisible");
//sets all the featuredImage view to invisible!
                //sets all the featuredImageButtons to unChecked!
                for (int i = 0; i < mFeatureImageCollection.size(); i++){
                    ImageView mFeatureImageTemp = mFeatureImageCollection.get(i);
                    Log.i(TAG, "rendi tutti invisibile");
                    mFeatureImageTemp.setVisibility(View.INVISIBLE);                    

                    ToggleButton mFeatureImageButtonTemp = mFeatureImageButtonCollection.get(i);
                    mFeatureImageButtonTemp.setChecked(false);

                    mFeatureImageButtonTemp.setBackgroundResource(R.drawable.first_photo_off);
                }

                //mFeaturedImage.setVisibility(View.VISIBLE);

                Log.e(TAG, mFilePathList.get(position).toString());
                Log.e(TAG, Boolean.toString(isChecked));
                //if check make visible and viceversa
                if (isChecked) {
                    Log.e(TAG, "rendi visibile");
                    buttonView.setBackgroundResource(R.drawable.first_photo_on);
                    buttonView.setChecked(true);
                    mFeaturedImage.setVisibility(View.VISIBLE);
                    mFeaturedImageSet = true;
                } else {
                    Log.e(TAG, "rendi invisibile");
                    buttonView.setChecked(false);
                    buttonView.setBackgroundResource(R.drawable.first_photo_off);
                    mFeaturedImage.setVisibility(View.INVISIBLE);
                    mFeaturedImageSet = false;
                }

                setFilePathListSequence(mFilePathList, buttonView, position);

            }
        });
    }



    public static ArrayList<String> getFilePathList(){
        return mFilePathList;
    }

    public void setFilePathListSequence(ArrayList<String> list, View v, int i){
        if (v.getVisibility() == View.VISIBLE) {
            String temp = list.get(i);
            list.remove(i);
            list.add(0, temp);
        }


        //serve per verificare la corretteza della modifica alla lista dei file path
        for (int j = 0; j < list.size(); j++){
            Log.e(TAG, "list item: " + j + " "+ list.get(j).toString());
        }

    }

    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;
    }
}
Was it helpful?

Solution

You use ArrayAdapter in a wrong way. In your case it will be better to use BaseAdapter. ArrayAdapter already have ArrayList of objects, in you case you create you own list. So when you call remove on you adapter it does nothing. Check sources - http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/4.4.2_r1/android/widget/ArrayAdapter.java#ArrayAdapter.remove%28java.lang.Object%29

I think it is not a good decision to send List of items to each view. If you want to delete item from itself. you could set some callback to the view.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top