title: Android - loading wrong RecyclerView item data asyncronously
body: <p>I'm creating a simple app that shows a list of item. Some of the item data is loaded in another thread, but when i scroll fast it shows the wrong data.</p>
  
  <p>Here is the code for the adapter:</p>
  
  <pre><code>package com.lorenzorapetti.pokedex.adapter;
  
  import android.content.Context;
  import android.os.AsyncTask;
  import android.support.v7.widget.RecyclerView;
  import android.util.Log;
  import android.view.LayoutInflater;
  import android.view.View;
  import android.view.ViewGroup;
  import android.widget.ImageView;
  import android.widget.TextView;
  
  import com.lorenzorapetti.pokedex.R;
  import com.lorenzorapetti.pokedex.Utils;
  import com.lorenzorapetti.pokedex.model.PokemonSpecies;
  import com.lorenzorapetti.pokedex.model.PokemonType;
  import com.squareup.picasso.Picasso;
  
  import org.apache.commons.lang3.StringUtils;
  
  import java.lang.ref.WeakReference;
  import java.util.List;
  
  import butterknife.Bind;
  import butterknife.ButterKnife;
  
  public class PokemonSpeciesAdapter extends RecyclerView.Adapter&lt;PokemonSpeciesAdapter.ViewHolder&gt; {
  
      private List&lt;PokemonSpecies&gt; mData;
      private Context context;
  
      public PokemonSpeciesAdapter(Context context, List&lt;PokemonSpecies&gt; data) {
          this.context = context;
          mData = data;
      }
  
      @Override
      public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
  
          View itemView =((LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE))
                  .inflate(R.layout.pokemon_species_item, parent, false);
  
          return new ViewHolder(itemView);
      }
  
      @Override
      public void onBindViewHolder(final ViewHolder holder, int position) {
  
          PokemonSpecies item = mData.get(position);
          holder.position = position;
  
          Picasso.with(context)
                  .load(Utils.getSugimoriThumbUrl(item.getIdentifier()))
                  .placeholder(R.mipmap.ic_launcher)
                  .error(R.mipmap.ic_launcher)
                  .into(holder.image);
  
          String identifier = "pokemon_species_" + Utils.convertIdentifier(item.getIdentifier())
                  + "_name";
          holder.textPrimary.setText(context.getResources().getString(
                  context.getResources().getIdentifier(identifier, "string", context.getPackageName())
          ));
          holder.textSecondary.setText("#" + StringUtils.leftPad(item.getId().toString(), 3, "0"));
  
          new AsyncLoad(item, holder, position).execute();
      }
  
      @Override
      public int getItemCount() {
          return mData != null ? mData.size() : 0;
      }
  
      @Override
      public long getItemId(int position) {
          return mData.get(position).getId();
      }
  
      public class ViewHolder extends RecyclerView.ViewHolder {
          @Bind(R.id.pokemon_species_image) ImageView image;
          @Bind(R.id.pokemon_species_name) TextView textPrimary;
          @Bind(R.id.pokemon_species_number) TextView textSecondary;
          @Bind(R.id.pokemon_species_primary_type)
          TextView typePrimary;
          @Bind(R.id.pokemon_species_secondary_type)
          TextView typeSecondary;
          int position;
  
          public ViewHolder(View itemView) {
              super(itemView);
              ButterKnife.bind(this, itemView);
          }
      }
  
      private class AsyncLoad extends AsyncTask&lt;Void, Void, AsyncLoad.AsyncItem&gt; {
  
          private WeakReference&lt;PokemonSpecies&gt; itemData;
          private WeakReference&lt;ViewHolder&gt; viewHolder;
          private int mPosition;
  
          public AsyncLoad(PokemonSpecies item, ViewHolder viewHolder, int position) {
              this.itemData = new WeakReference&lt;&gt;(item);
              this.viewHolder = new WeakReference&lt;&gt;(viewHolder);
              mPosition = position;
          }
  
          @Override
          protected AsyncLoad.AsyncItem doInBackground(Void... params) {
  
              List&lt;PokemonType&gt; pokemonTypes = itemData.get().getDefaultPokemon().getPokemonTypes();
              Log.d("App", "position: " + mPosition + ", holderPosition: " + viewHolder.get().position
                              + ", pokemon: " + itemData.get().getIdentifier() + ", size: " + pokemonTypes.size());
              String primaryIdentifier = "type_" +
                      Utils.convertIdentifier(pokemonTypes.get(0).getType().getIdentifier());
              AsyncLoad.AsyncItem asyncItem = new AsyncLoad.AsyncItem();
  
              asyncItem.primaryText = context.getResources().getString(
                      context.getResources().getIdentifier(primaryIdentifier + "_name", "string",
                              context.getPackageName()));
  
              asyncItem.primaryColor = context.getResources().getColor(
                      context.getResources().getIdentifier(primaryIdentifier, "color",
                              context.getPackageName()));
  
              if (pokemonTypes.size() == 2) {
                  String secondaryIdentifier = "type_" +
                          Utils.convertIdentifier(pokemonTypes.get(1).getType().getIdentifier());
                  asyncItem.secondaryText = context.getResources().getString(
                          context.getResources().getIdentifier(secondaryIdentifier + "_name", "string",
                                  context.getPackageName()));
                  asyncItem.secondaryColor = context.getResources().getColor(
                          context.getResources().getIdentifier(secondaryIdentifier, "color",
                                  context.getPackageName()));
              }
  
              return asyncItem;
          }
  
          @Override
          protected void onPostExecute(AsyncLoad.AsyncItem asyncItem) {
              ViewHolder holder = viewHolder.get();
              if (mPosition == holder.position) {
                  holder.typePrimary.setText(asyncItem.primaryText);
                  holder.typePrimary.setBackgroundColor(asyncItem.primaryColor);
                  if (asyncItem.secondaryText != null) {
                      holder.typeSecondary.setText(asyncItem.secondaryText);
                      holder.typeSecondary.setBackgroundColor(asyncItem.secondaryColor);
                  }
              }
          }
  
          protected class AsyncItem {
              String primaryText;
              int primaryColor;
              String secondaryText;
              int secondaryColor;
          }
      }
  
  }
  </code></pre>
  
  <p>What can i do to load the exact data?</p>