java - layoutinflater - Layout incondizionato, inflazione da adattatore vista: deve utilizzare il modello View Holder




view container android (3)

Ricevo il seguente avviso in eclissi:

Flusso di layout incondizionato dall'adattatore di visualizzazione: utilizzare il modello del supporto di visualizzazione (utilizzare la vista riciclata passata in questo metodo come secondo parametro) per uno scorrimento più fluido.

sopra:

convertView = vi.inflate(R.layout.activity_friend_list_row, parent, false);

Ho un adattatore di base con un CheckBox implementato e ho aggiunto un tag per far funzionare il CheckBox.

Ecco il codice:

 public View getView(final int position, View convertView, ViewGroup parent) 
  {

    ViewHolder mViewHolder;
    mViewHolder = new ViewHolder();
    LayoutInflater vi = (LayoutInflater) activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);

    convertView = vi.inflate(R.layout.activity_friend_list_row, parent, false);

    mViewHolder.cb = (CheckBox) convertView.findViewById(R.id.checkBox);

    convertView.setTag(mViewHolder);

    if (InviteFriends.isChecked[position] == true)
    {
        mViewHolder.cb.setChecked(true);
    }
    else
    {
        mViewHolder.cb.setChecked(false);
    }

    mViewHolder.cb.setOnCheckedChangeListener(new OnCheckedChangeListener() 
    {
        @Override
        public void onCheckedChanged(CompoundButton buttonView, boolean ischecked) 
        {
            if (buttonView.isChecked())
            {
                InviteFriends.isChecked[position] = true;

            }
            else
            {
                InviteFriends.isChecked[position] = false;
            }
        }
    });

    TextView friendsname  = (TextView) convertView.findViewById(R.id.friendsName); // title
    ImageView thumb_image = (ImageView) convertView.findViewById(R.id.list_image); // thumb image

    HashMap<String, String> song = new HashMap<String, String>();
    song = data.get(position);

    // Setting all values in listview
    friendsname.setText(song.get(InviteFriends.KEY_DISPLAY_NAME));
    imageLoader.DisplayImage(song.get(InviteFriends.KEY_IMAGEPROFILE_URL), thumb_image);


    return convertView;
}

I risultati stanno arrivando correttamente. Come posso risolvere questo avvertimento? Non sono ancora in grado di ottenere una soluzione per questo?

Grazie!

https://code.i-harness.com


Flusso di layout incondizionato dall'adattatore di visualizzazione: utilizzare il modello del supporto di visualizzazione (utilizzare la vista riciclata passata in questo metodo come secondo parametro) per uno scorrimento più fluido.

Significa che è necessario utilizzare il modello View Holder nell'Adapter. Il punto di utilizzo di View Holder consiste nel riutilizzare le visualizzazioni perché il gonfiaggio e l'utilizzo di findViewById sono lenti.

Quando stai usando il seguente codice:

public View getView(final int position, View convertView, ViewGroup parent) {

    ViewHolder mViewHolder;
    mViewHolder = new ViewHolder();
    LayoutInflater vi = (LayoutInflater) activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    convertView = vi.inflate(R.layout.activity_friend_list_row, parent, false);
    mViewHolder.cb = (CheckBox) convertView.findViewById(R.id.checkBox);
    convertView.setTag(mViewHolder);

    ...

    return convertView;

} 

non stai riutilizzando le visualizzazioni ma invece crei sempre nuove visualizzazioni.

Devi cambiare il tuo codice in qualcosa di simile (controlla il commento):

// class for holding the cached view
static class ViewHolder {
   TextView tvFriendsName;
   ImageView imvThumbImage;
   CheckBox cbInviteFriend;
}

public View getView(final int position, View convertView, ViewGroup parent) {

    // holder of the views to be reused.
    ViewHolder viewHolder;

    // get data based on the position
    HashMap<String, String> song = data.get(position);

    // if no previous views found
    if (convertView == null) {
       // create the container ViewHolder
       viewHolder = new ViewHolder();

       // inflate the views from layout for the new row
       LayoutInflater inflater = LayoutInflater.from(parent.getContext());
       convertView = inflater.inflate(R.layout.rowlayout, parent, false);

       // set the view to the ViewHolder.
       viewHolder.cbInviteFriend = convertView.findViewById(R.id.checkBox);
       viewHolder.tvFriendsName  = convertView.findViewById(R.id.friendsName);
       viewHolder.imvThumbImage = convertView.findViewById(R.id.list_image); 

       // save the viewHolder to be reused later.
       convertView.setTag(viewHolder);
    } else {
       // there is already ViewHolder, reuse it.
       viewHolder = (ViewHolder) convertView.getTag();
    }

    // now we can set populate the data via the ViewHolder into views
    viewHolder.tvFriendsName.setText(song.get(InviteFriends.KEY_DISPLAY_NAME));
    imageLoader.DisplayImage(song.get(InviteFriends.KEY_IMAGEPROFILE_URL), viewHolder.imvThumbImage);
    viewHolder.cbInviteFriend.isChecked(InviteFriends.isChecked[position]);

    return convertView;
}

Il mio suggerimento è provare a usare convertView = vi.inflate(R.layout.activity_friend_list_row, null); convertView = vi.inflate(R.layout.activity_friend_list_row, parent, false); di convertView = vi.inflate(R.layout.activity_friend_list_row, parent, false); questo può aiutarti.

: - okey .. insted di accedere come questo TextView friendsname = (TextView) convertView.findViewById(R.id.friendsName); // title ImageView thumb_image = (ImageView) convertView.findViewById(R.id.list_image); // thumb image TextView friendsname = (TextView) convertView.findViewById(R.id.friendsName); // title ImageView thumb_image = (ImageView) convertView.findViewById(R.id.list_image); // thumb image TextView friendsname = (TextView) convertView.findViewById(R.id.friendsName); // title ImageView thumb_image = (ImageView) convertView.findViewById(R.id.list_image); // thumb image devi usare la classe viewholder nell'adattatore

per esempio

static class ViewHolder {
    public TextView text;
    public ImageView image;
  }

  @Override
  public View getView(int position, View convertView, ViewGroup parent) {
    View rowView = convertView;
    // reuse views
    if (rowView == null) {
      LayoutInflater inflater = context.getLayoutInflater();
      rowView = inflater.inflate(R.layout.rowlayout, null);
      // configure view holder
      ViewHolder viewHolder = new ViewHolder();
      viewHolder.text = (TextView) rowView.findViewById(R.id.TextView01);
      viewHolder.image = (ImageView) rowView
          .findViewById(R.id.ImageView01);
      rowView.setTag(viewHolder);
    }

    // fill data
    ViewHolder holder = (ViewHolder) rowView.getTag();
    String s = names[position];
    holder.text.setText(s);
    if (s.startsWith("Windows7") || s.startsWith("iPhone")
        || s.startsWith("Solaris")) {
      holder.image.setImageResource(R.drawable.no);
    } else {
      holder.image.setImageResource(R.drawable.ok);
    }

    return rowView;
  }

dovresti iniziare la vista di conversione solo se è nullo

queste linee

LayoutInflater vi = (LayoutInflater) activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);

convertView = vi.inflate(R.layout.activity_friend_list_row, parent, false);
// [...] the rest of initialization part
// [...] some changes that must be done at refresh
return convertView;

dovrebbe assomigliare a questo:

if (convertView == null) {
    LayoutInflater vi = (LayoutInflater) activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);

    convertView = vi.inflate(R.layout.activity_friend_list_row, parent, false);
    // [...] the rest of initialization part
}
// [...] some changes that must be done at refresh
return convertView;

l'obiettivo è di riciclare la vista già esistente in quella lista, non di iniziarla ogni volta che la si visualizza durante lo scorrimento della lista, ad esempio.





layout-inflater