0

Apologies in advance if this is a dumb question. I have searched the web for an answer to my issue, but have not found anything that would help.

I have a ListView and a CustomViewAdapter within a Fragment. This works fine. The list is displayed correctly.

What I have a problem with is if a row within the list changes, although the row gets updated, the actual list does not. To put it in context, what I have is a list of favorites and they are shown in a favorites fragment. However, if the user "unfavorites" an item, even though the icon that shows it is a favorite change, the actual list still shows that item, rather than refresh the list and remove that item from the list.

As I said, I have tried all the solutions I could find related to this issue, such as calling notifyDataSetChanged with the adapter.

My code in the fragment:

public void ShowFavourites(){
    globalVariable = ((GlobalClass) getActivity().getApplicationContext());
    JCDatabaseHelper helper = new JCDatabaseHelper(getActivity().getBaseContext());

    ArrayList<ArticleItem> rowItems = new ArrayList<>();
    ArticleItem myItem1;
    String[] columnNames = {"_id", "Column1", "Column2", "Column3",
            "Column4", "Column5", "Column6", "Column7"};
    MatrixCursor matrixCursor = new MatrixCursor(new String[]{"_id",
            "Column1", "Column2", "Column3", "Column4", "Column5", "Column6", "Column7" });
    int[] to = new int[]{R.id.id, R.id.imageButton, R.id.title, R.id.year, R.id.authors,
            R.id.favs, R.id.read, R.id.readOnLine};
    final ListView listView = (ListView) getActivity().findViewById(android.R.id.list);
    ArrayList<Favourites> favouritesArrayList = helper.GetFavourites();
     for (Favourites articleItem : favouritesArrayList) {
          // code to access items
          //then...
          matrixCursor.addRow(new Object[]{k, imgFile,Title, Year , Authors, favIcon , btn1.getText(), btn2.getText() });
          myItem1 = new ArticleItem(ID, Title, Year);
          rowItems.add(myItem1);
     }
    CustomListViewAdapter customAdapter;
    ListView yourListView;
    customAdapter = new CustomListViewAdapter(getActivity().getBaseContext(),
            R.layout.article_row, rowItems);
    yourListView.setAdapter(customAdapter);
    customAdapter.notifyDataSetChanged();
}

The code in CustomListViewAdapter:

public class CustomListViewAdapter extends ArrayAdapter<ArticleItem> {

  ArrayList<ArticleItem> _rowItems;
  ArticleItem item;
  View row;

  public CustomListViewAdapter(Context context, int resourceId,
                             ArrayList<ArticleItem> articleItems) {
    super(context, resourceId,articleItems);
    this.context = context;
    _rowItems = articleItems;
    }

  @Override
  public View getView(final int position, View convertView, ViewGroup parent){
    row = convertView;
    item = _rowItems.get(position);
    if (row == null) {
       LayoutInflater mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
       row = mInflater.inflate(R.layout.article_row, parent, false);
    }

    // other code to set TextViews, etc ...
    final int FavYes = R.drawable.favourite;
    final int FavNo = R.drawable.favourite_outline;

    final ImageButton favBtn = (ImageButton) row.findViewById(R.id.favs);
    if (Favs.equals("Y")){
        favBtn.setImageResource(FavYes);
    }
    else favBtn.setImageResource(FavNo);

    favBtn.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
        JCDatabaseHelper helper = new JCDatabaseHelper(getContext());
            item = _rowItems.get(position);
            ID = item.getID();
            Title = item.getTitle();
            String NewFavs;
            if (Favs.equals("N")){
                NewFavs = "Y";
                favBtn.setImageResource(FavYes);
                helper.UpdateFavourite("FavouritesTable", ID, NewFavs);
            }
            else {
                NewFavs = "N";
                favBtn.setImageResource(FavNo);
                helper.UpdateFavourite("FavouritesTable", ID, NewFavs);
                // THIS ACTION SHOULD TAKE THIS ROW FROM THE LIST AND RESHOW THE LIST. 
            }
     }
    });

 return row;
}

I have tried the following answers: 1. How to refresh Android listview? but it doesn't work. Maybe because I don't call it correctly. 2. notifyDataSetChanged() in Fragment is not refreshing listview Other questions/answers were dealing with similar, but not the same issue.

Any help will be much appreciated. Thanks

Mehul Kabaria
  • 6,404
  • 4
  • 25
  • 50
user3079872
  • 191
  • 1
  • 5
  • 15

2 Answers2

1

looking at the code I think notifyDataSetChanged method should be working in this case.

The key point is that you should modify the collection before invoking notifyDataSetChanged, since this method is only going to take your collection (_rowItems) and inflating every item again into the ListView. So if the collection still contains that item, that is going to stay in the list.

Since you are setting your articleItems to the _rowItems field when constructing the adapter, I think the fastest approach could be to call listView.getAdapter().removeItem(itemNotFavorite). Note that to do this you have to cast your adapter to be an ArrayAdapter before :)

Another chance, maybe a little cleaner can be to create a setter in the adapter to overwrite your collection, and then rely on notifyDataSetChanged.

Let me know if some of this works ;)

Marino
  • 800
  • 1
  • 12
  • 26
  • thank you. I think I understand what your suggestions, but obviously not enough as I would not know how to code them. Would you be able to provide some code? – user3079872 Aug 08 '17 at 13:37
  • I think that the `notifyDataSetChanged` should work, but I don't know how to call it from within the CustomListViewAdapter ... would you know how I can do that? Thanks! – user3079872 Aug 08 '17 at 15:33
  • I have tried what you said, that the notifyDataSetChanged should work. The issue I had was that I was not calling it right or from the right place. I will add what I have done as an answer, in case it helps anyone else, but thank you very much for your explanations. They helped – user3079872 Aug 08 '17 at 21:39
  • @user3079872 I'm Happy that helped! Cheers :) – Marino Aug 09 '17 at 08:23
0

I have come up with an answer through Marino's answer, so have marked their answer as the correct one. I just wanted to show the code I added in case it helps anyone else. I added the following to the CustomListViewAdapter I am just posting part of the code above)

  favBtn.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
    JCDatabaseHelper helper = new JCDatabaseHelper(getContext());
        item = _rowItems.get(position);
        ID = item.getID();
        Title = item.getTitle();
        String NewFavs;
        if (Favs.equals("N")){
            NewFavs = "Y";
            favBtn.setImageResource(FavYes);
            helper.UpdateFavourite("FavouritesTable", ID, NewFavs);
        }
        else {
            NewFavs = "N";
            favBtn.setImageResource(FavNo);
            helper.UpdateFavourite("FavouritesTable", ID, NewFavs);
            // Here is what helped!
            _rowItems.remove(item); //this removes the item that has been set as no longer a favourite
            CustomListViewAdapter.this.notifyDataSetChanged(); // this I suppose refreshes the adapter
        }
 }
});

Thanks also to @Marcos, who gave me a clue on what to do.

user3079872
  • 191
  • 1
  • 5
  • 15