GridView的BaseAdapter:并不总是在notifyDatasetChanged()上调用getView()

时间:2016-04-18 06:37:09

标签: android baseadapter notifydatasetchanged

我有一个用于GridView的自定义BaseAdapter。我在上面调用notifyDatasetChanged()。但是,未调用getView(),因此我的UI未更新。

我已经调试了这个并且看到底层数据是正确的,包含正确的启用状态,但是UI没有更新,因为没有调用getView()。

这是我的适配器:

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();
    }
  }
}

我在MyActivity中调用notifyDatasetChanged():

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);

  }

}

触发所有这一切的checkChanged位于片段中:

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;

  }
}

我迷失了为什么这不起作用。我怎样才能让它发挥作用?

在调用getView时,列表具有正确的数据,在某些情况下UI会刷新,但在其他情况下,不会调用getView。我需要触摸UI才能进行刷新。

编辑:

我也尝试过这种方法:

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

即使此代码运行,仍未调用getView()。

2 个答案:

答案 0 :(得分:1)

更新你的setContentView,如下所示:

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

    mMy_list.setAdapter(mMyAdapter);

  }

答案 1 :(得分:0)

无论何时更改要传递给适配器并调用notifyDatasetChanged()的ArrayList的值,它都能正常工作。

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

如果对arrayList的大小进行一些修改,则调用notifyDatasetChanged,请注意内部适配器构造函数,只需分配给引用,不要创建新的Object。

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

在您的代码中,请确保您在哪里更新列表,还要更新适配器。

其他方式 在适配器中创建一个函数,它将param作为列表,内部函数将其分配给适配器列表实例并执行notifyDatasetChanged。

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

将此功能称为

mAdapter.refereshData(list);