Domanda

I built a custom adapter in order to correctly display some data in a list view. In onContextItemSelected() the dataset is changed and I call notifyDataSetChanged() to update the list view. Apparently the adapter's getView() method only gets invoked after onContextItemSelected() terminated.

  1. Why?
  2. In contextItemSelected() I call the method editLanguage() that needs to access a button which is supposed to be inflated earlier by getView(). As getView() is called "too late" i get a NullpointerException.

The button is inflated in "getView" which should be invoked by "notifyDataSetChanged".

public boolean onContextItemSelected(MenuItem item) {
   AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo)   item.getMenuInfo();
   languageItem selectedLanguage = languages.get((int) info.id);
   switch (item.getItemId()) {
     case EDIT: 
      languages.get((int) info.id).setSelected(true); 
      adapter.update(languages); 
      adapter.notifyDataSetChanged(); // call getView() of the adapter!
      editLanguage(selectedLanguage); // access a button that was inflated by getView()
//...


public View getView(int position, View convertView, ViewGroup parent) {    
//...         
switch(getItemViewType(position)) {
  case DEFAULT_LINE:
   //...
   break;
  case EDIT_LINE: 
   convertView = LayoutInflater.from(getContext()).inflate(R.layout.language_row_edit, null); // contains button bu_language_change
   viewHolder.button = (Button) convertView.findViewById(R.id.bu_language_change);
   break;
  //...

I get null when trying to access the button (bu_language_change).

private void editLanguage(final LanguageItem languageToEdit) {

Button editButtonConfirm = (Button) this.findViewById(R.id.bu_language_change); // null
È stato utile?

Soluzione

notifyDataSetChanged does NOT force adapter to call sequence of getView method instantly. It rather tells that it should be refreshed and it happens asynchronously. If you want to achieve that goal you mentioned I have 2 ideas:

  1. Add bu_language_change Button to your view from DEFAULT_LINE with visibility level View.GONE then in your EDIT_LINE you change visibility View.VISIBLE. View.GONE makes your layout to behave as it has no such child(bu_language_change Button).
  2. Somehow notify from getView() method that inflating view has been done, and call editLanguage method. But it's a bad idea. Romain Guy in here says:

... getView() is not guaranteed to be called exactly once per item ...

Or call this editLanguage method from the body of getView method, that would have solved your problem.

I recommend to watch Google I/O about ListViews. It's over here

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top