-1

I have a custom BaseAdapter that is used for a GridView. I call notifyDatasetChanged() on it. However, getView() is not called so my UI is not updated.

I have debugged this and saw that the underlying data is correct containing the correct enabled status, however the UI does not update, because getView() is not called.

This is my adapter:

public class MyAdapter extends BaseAdapter {

  private List<? extends MyListItem> mItems;
  protected Context mContext;
  private LayoutInflater mInflater;
  private int mLayout;

  static class ItemView {
    View mLayout;
    ImageView mIcon;
    TextView mCaption;
  }

  public MyAdapter(Context pContext, List<? extends MyListItem> items, int layout) {
    mContext = pContext;
    mItems = items;
    mLayout = layout;

    this.mInflater = LayoutInflater.from(pContext);
  }

  @Override
  public int getCount() {
    if (mItems == null)
      return 0;
    return mItems.size();
  }

  @Override
  public MyListItem getItem(int position) {
    if (mItems == null)
      return null;
    return mItems.get(position);
  }

  @Override
  public long getItemId(int position) {
    return position;
  }

  @Override
  public View getView(int position, View convertView, ViewGroup parent) {
    ItemView holder;
    final MyListItem lItem = getItem(position);
    if (convertView == null) {
      holder = new ItemView();
      convertView = mInflater.inflate(mLayout, null);

      holder.mLayout = convertView.findViewById(R.id.LinearLayout1);
      holder.mIcon = (ImageView) convertView.findViewById(R.id.imageView1);
      holder.mCaption = (TextView) convertView.findViewById(R.id.textView1);

      holder.mLayout.setEnabled(lItem.isEnabled());
      holder.mCaption.setEnabled(lItem.isEnabled());

      if (lItem.getIntent() != null) {
        holder.mLayout.setClickable(true);
        convertView.setOnClickListener(buildOnClickListener(lItem.getIntent()));
      }

      convertView.setTag(holder);
    }
    holder = (ItemView) convertView.getTag();
    if (lItem != null) {
      convertView.setVisibility(lItem.isVisible() ? View.VISIBLE : View.GONE);

      holder.mIcon.setImageDrawable(lItem.getIcon(mContext));

      holder.mCaption.setText(lItem.getCaption(mContext));

      holder.mLayout.setEnabled(lItem.isEnabled());
      holder.mCaption.setEnabled(lItem.isEnabled());
      holder.mIcon.setEnabled(lItem.isEnabled());

      holder.mLayout.setClickable(!lItem.isEnabled());
      holder.mCaption.setClickable(!lItem.isEnabled());
      holder.mIcon.setClickable(!lItem.isEnabled());
    }

    return convertView;
  }

  protected OnClickListener buildOnClickListener(final Intent pIntent) {
    return new OnClickListener() {

      @Override
      public void onClick(View v) {
        mContext.startActivity(pIntent);
      }
    };
  }

  public void invalidate() {

  }

@Override
  public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
    ((MyPosition) buttonView.getTag()).setChecked(isChecked);
    if (mListener != null) {
      mListener.onItemsCheckChanged();
    }
  }
}

I am calling notifyDatasetChanged() in MyActivity:

public class MyActivity extends Activity {


  private MyAdapter mMyAdapter;
  private GridView mMy_list;
  private MyItem mButton;

  mMyAdapter = new MyAdapter(this, myObjects.getMyItems(), R.layout.my_items);

public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.layout_activity, true);
  }

public void setButtonEnabled(boolean enabled) {
    mButton.setEnabled(enabled);
    invalidateActionbar();
  }

  public void invalidateActionbar() {
    refreshItems();
  }


  protected void refreshItems() {
    mMyAdapter.notifyDataSetChanged();
  }

  public void setContentView(int id, boolean useScrollView) {
    View mOverlayView = mGrid.init(this, mBaseView);
    mMy_list = (GridView) findViewById(R.id.my_list);

    mMy_list.setAdapter(mMyAdapter);

    setContentView(mOverlayView);

  }

}

The checkChanged that triggers all of this is in the Fragment:

public class MyFragment extends Fragment {


  @Override
  public void onItemsCheckChanged() {
    final Activity activity = getActivity();

    if (activity != null && activity instanceof MyActivity) {
      final MyActivity myActivity = (MyActivity) getActivity();
      if (myActivity != null) {
        if (mAdapter != null) {
          myActivity.setButtonEnabled(true);
        }
      }
    }
  }

}


public class MyItem {
    private boolean mEnabled;   
    public void setEnabled(boolean enabled) {
    this.mEnabled = enabled;

  }
}

I am lost as to why this is not working. How can I get this to work?

The list has the proper data, in some cases the UI refreshes, when getView is called, but in other cases getView is not called. I need to touch the UI in order for the refresh to happen.

EDIT:

I also tried this method:

public void refresh(){
    List<MyListItem> items= new ArrayList<MyListItem>(mItems);
    mItems.clear();
    notifyDataSetChanged();
    mItems.addAll(items); 
    notifyDataSetChanged();
  }

Still getView() is not called even though this code runs.

barq
  • 3,681
  • 4
  • 26
  • 39

2 Answers2

1

update your setContentView as below:

public void setContentView(int id, boolean useScrollView) {
    setContentView(id);
    mMy_list = (GridView) findViewById(R.id.my_list);

    mMy_list.setAdapter(mMyAdapter);

  }
Sanjay Kakadiya
  • 1,596
  • 1
  • 15
  • 32
0

It works whenever you are changing values of ArrayList which you are passing to adapter and calling notifyDatasetChanged().

MyList myList=myObjects.getMyItems();
MyAdapter mMyAdapter=new MyAdapter(this,myList); myList.add();
mMyAdapter.notifyDatasetChanged();

if some modification in size of arrayList then call notifyDatasetChanged and please note inside adapter constructor just assign to reference dont create new Object.

MyList myList;
MyAdapter(Context context,MyList myList)
{
this.myList=myList;
} 

In your code please make sure where ever you are updating list, update adapter also.

Other way Create one function inside adapter which takes param as your list and inside function assign it to adapter list instance and do notifyDatasetChanged.

/*Use this method instead where ever you are calling notifyDatasetChanged() directly*/
public void refereshData(List myList)
{
this.myList=myList;
notifyDatasetChanged()
}

call this function like

mAdapter.refereshData(list);
Godfather
  • 833
  • 9
  • 14
  • The size of the ArrayList does not change, only the status of one of the elements changes. Could this be the problem? – barq Apr 18 '16 at 07:53
  • No that won't be problem as items are changing.once some property is getting changed call notifyDatasetChanged().make sure you have same reference and those changes are reflected in your list also. – Godfather Apr 18 '16 at 09:52
  • The changes are reflected in the list, maybe this is an Android bug then. Sometimes it refreshes, sometimes it does not. – barq Apr 18 '16 at 11:18
  • No it is not Android bug,some minor but you can try other approach.See my updated answer – Godfather Apr 18 '16 at 11:31
  • I already tried something like refreshData, clearing the Array and adding items. Still the same. Maybe notifyDataSetChanged is not registering any difference, because only one field has changed in the object? – barq Apr 18 '16 at 11:34
  • I edited my question to show what method I tried without success. Removing all data, notifyDataSetChanged and adding again, notifyDataSetChanged. Still, getView() is not called. Maybe GridView has a problem with BaseAdapter? – barq Apr 18 '16 at 11:51