0

I have implemented a custom adapter and listItemView. The adapter sets an onlclick listener to a button that is on the listItemView. The onclick listener simply calls a private method I have in the adapter and passes it the position of the item to be removed. I know the position is correct because the database removes the proper item. I have found similar questions but have not been able to adapt the answers to work for me. Ideas and thoughts are greatly appreciated. Thanks.

Here is the full adapter class

public class FoodListAdapter extends ArrayAdapter<FoodListItem> {

    //private
    private int type;

    public FoodListAdapter(Context context, ArrayList<FoodListItem> _objects) {
        super(context, 0, _objects);
        type = 0;       
    }

    public FoodListAdapter(Context context, ArrayList<FoodListItem> _objects, int _type) {
        super(context, 0, _objects);
        type = _type;       
    }

    @Override
    public View getView(int position, View reusableView, ViewGroup parent)
    {
        //Cast the reusable view to a listAdpaterItemView
        FoodListItemView listItemView = (FoodListItemView) reusableView;

        //Check if the listAdapterItem is null
        if(listItemView == null)
        {
            //If it is null, then create a view.
            listItemView = FoodListItemView.inflate(parent, this, type);
        }

        if (type == 2)
        {
            Button deleteButton = (Button) listItemView.findViewById(R.id.listItemViewDeleteBTN);
            deleteButton.setTag(new Integer(position));
        }

        //Now we need to set the view to display the data.
        listItemView.setData(getItem(position));

        return listItemView;
    }
}

Here is a portion of my code used in fragment. Note that I have a private variable decalred in the class for listAdapter, though I don't think I need that.

    private void displayListForDate(Calendar _date)
{
    //get the list view
    ListView listView = (ListView) getView().findViewById(1);
    //Clear the listview by removing the listadapter and setting it to null.
    //listView.setAdapter(null);

    //First we must get the items.
    Global global = (Global) getActivity().getApplicationContext();
    DietSQLiteHelper database = global.getDatabase();

    //Create a list to hold the items we ate. This list will then be added to the listView.
    final ArrayList<FoodListItem> consumedList;
    //Add the items to the array.
    consumedList = database.getConsumed(_date.getTimeInMillis());

    //Create an adapter to be used by the listView
    listAdapter = new FoodListAdapter(getActivity().getBaseContext(), consumedList, 2);

    //Add the adapter to the listView.
    listView.setAdapter(listAdapter);

    listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
        @Override
        public void onItemClick(AdapterView<?> adapterView, View view, int position, long l) {
            consumedList.remove(position);
            listAdapter.notifyDataSetChanged();
        }
    });
}
n01d3a
  • 17
  • 5

3 Answers3

0

If you didn't implement "equals" method of FoodListItem, try to implements it.

issathink
  • 1,220
  • 1
  • 15
  • 25
  • This is implemented, and I went through debugger to make sure true is returned when the ID of the argument matches the item itself. – n01d3a Dec 29 '14 at 15:39
0

I would suggest, that you just update the underlying data, in your case its ArrayList<FoodItems>.

In your Adapter make this simple method and change :

private List<FoodListItem> myList = new ArrayList<FoodListItem>();

public FoodListAdapter(Context context, List<FoodListItem> myList) {
    super(context, 0, myList);
    type = 0;
    this.myList = myList;
}

public FoodListAdapter(Context context, List<FoodListItem> myList, int _type) {
    super(context, 0, myList);
    type = _type; 
    this.myList = myList;     
}

// Also update your getView() method to use myList!
@Override
public View getView(int position, View reusableView, ViewGroup parent)
{
   ...
   listItemView.setData(myList.get(position));

public void removeItem(int positio){
    if(myList != null){
        myList.remove(position);
    }
}

And then in class, you are creating the adapter (Activity/Fragment), just call the method.

// Update the underlying ArrayAdapter
adapter.removeItem(position);
// Notify the adapter, the data has changed
adapter.notifyDataSetChanged();

Also, you shouldnt open connection to your SQLiteDatabase on UI thread, because you are blocking it. You never know, how fast is the reading from disk going to be. If it takes too long, user can think, that your application froze and therefore, he leaves, which you dont want. I would suggest to use AsyncTask, you will find a lot of examples.

Vojtěch Pešek
  • 1,070
  • 8
  • 25
  • I was hoping to stay away from implementing the list myself when the adapter provides one for you. I will also need to override some methods won't I. Also, how will I call remove from my fragment when I add the clickListener to the button in the adapter; if you look every row in the list has a delete button. I will look into your recommendation about AsyncTask, however I don't want the UI to continue until the data has been updated. Maybe a waiting screen will suffice. – n01d3a Dec 29 '14 at 15:41
  • I have made the changes you suggested and still have the same issue. I must be overlooking something. – n01d3a Dec 29 '14 at 19:27
  • @n01d3a it looks like, you have to set Listener on ListView and remove the item from ArrayList. Then notify the adapter and it should refresh itself correctly. It means, you do this code in your Activity/Fragment, not in the adapter. Try looking at this: http://stackoverflow.com/questions/18444671/remove-item-in-arrayadapterstring-in-listview – Vojtěch Pešek Dec 29 '14 at 19:31
  • I added an onitemClickListener to the list, get the position, and remove the item at position from the list. Then call notifyOnDataSetChagned. I will update post above with relevant code from fragment. – n01d3a Dec 29 '14 at 19:50
0

I went through and cleaned up my code and it now works, here is the working code. I really don't know exactly the difference other than I updated the IDs that I was using to assign and get views. If anyone can explain the cause for the issue I was having I would appreciate it.

Here is the snippet from my fragment where I create the list view and assign an adapter.

private void displayListForDate(Calendar _date)
{
    //get the list view
    ListView listView = (ListView) getView().findViewById(R.id.listView);
    //Clear the listview by removing the listadapter and setting it to null.
    //listView.setAdapter(null);

    //First we must get the items.
    Global global = (Global) getActivity().getApplicationContext();
    DietSQLiteHelper database = global.getDatabase();

    //Create a list to hold the items we ate. This list will then be added to the listView.
    ArrayList<FoodListItem> consumedList;
    //Add the items to the array.
    consumedList = database.getConsumed(_date.getTimeInMillis());

    //Create an adapter to be used by the listView
    listAdapter = new FoodListAdapter(getActivity().getBaseContext(), consumedList, 2);

    //Add the adapter to the listView.
    listView.setAdapter(listAdapter);
}

and here is my adapter class.

public class FoodListAdapter extends ArrayAdapter<FoodListItem> 
{

    //private
    private int type;

    public FoodListAdapter(Context context, ArrayList<FoodListItem> _objects) {
        super(context, 0, _objects);
        type = 0;       
    }

    public FoodListAdapter(Context context, ArrayList<FoodListItem> _objects, int _type) {
        super(context, 0, _objects);
        type = _type;       
    }

    @Override
    public View getView(int position, View reusableView, ViewGroup parent)
    {
        //Cast the reusable view to a listAdpaterItemView
        FoodListItemView listItemView = (FoodListItemView) reusableView;

        //Check if the listAdapterItem is null
        if(listItemView == null)
        {
            //If it is null, then create a view.
            listItemView = FoodListItemView.inflate(parent, type);
        }

        if (type == 2)
        {
            Button deleteButton = (Button) listItemView.findViewById(R.id.listItemViewDeleteBTN);
            deleteButton.setTag(new Integer(position));
            deleteButton.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    Integer tag = (Integer) view.getTag();
                    deleteItem(tag.intValue());
                }
            });
        }

        //Now we need to set the view to display the data.
        listItemView.setData(getItem(position));

        return listItemView;
    }

    private void deleteItem(int position)
    {
        FoodListItem item = getItem(position);
        Global global = (Global) getContext().getApplicationContext();

        DietSQLiteHelper database = global.getDatabase();
        database.removeConsumed(item.getID());

        remove(getItem(position));
    }
}
n01d3a
  • 17
  • 5