title: Android: ListView item click not working properly
body: <p>I am trying to implement a system of "favorites", so when a product is selected as favorite (by clicking a button), it is passed to a class called Favoris.java which displays all the favorite products as a ListView, which are all clickable to get more details on the clicked product. So far so good the listview works fine. </p>
  
  <p>But here is my main problem: <strong>when I click on one of those products to get its details, another product that is not on the favorites list is shown instead</strong>.</p>
  
  <p>I did notice something that will probably help: by adding a few favorites to my list, say 3, I noticed a pattern:</p>
  
  <ul>
  <li>When I click on the first product I added as a favorite, I get the details of the first product of all the available products (there is a main ListView with all the available products, which are all retrieved from a xml feed)</li>
  <li>When I click on the second product I added as a favorite, I get the details of the second product of all the available products.</li>
  <li>When I click on the third product I added as a favorite, I get the details of the third product of all the available products.</li>
  </ul>
  
  <p>I am currently passing the favorite products as class objects to the favorites class by transforming it using Gson and passing it using SharedPrefenreces, and the class Favoris.java gets that product back and transforms it back to a class object. </p>
  
  <p>So here is my listview of all my favorite products, you can see there are 4 products added as favorites: </p>
  
  <p><a href="https://i.stack.imgur.com/F742Z.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/F742Z.png" alt="favorites&#39; listview"></a>
  </p>
  
  <p>When clicking on the first product (Palais Héracles), I get another one (the first one of the default list of products) called "Château Périgord" (you can see I didn't add it as favorites since the star icon isn't black but white):</p>
  
  <p><a href="https://i.stack.imgur.com/RvpMR.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/RvpMR.png" alt="wrong product detail"></a>
  </p>
  
  <p>Here is the code of the details of a product:</p>
  
  <pre><code>public class ProduitDetail extends AppCompatActivity implements NavigationView.OnNavigationItemSelectedListener {
  
  /**
   * fields
   */
  private StackProduits produit;
  private Button butStar;
  /*images (main, thumbnails and gallery)*/
  private ArrayList&lt;String&gt; imagesUrlListThumb, imagesUrlListFull = new ArrayList&lt;String&gt;();
  private RecyclerAdapter recyclerAdapter;
  private String urlRecyclerThumb = "";
  /*view elements*/
  private RecyclerView recyclerView;
  private ImageView imgCurRecyclerView;
  private Button btnMailCurProduct, btnMailAgency;
  
  
  @Override
  protected void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      setContentView(R.layout.activity_produit_detail);
  
      /*get ids of the two star icons*/
      final int imgStarFull = R.drawable.ic_star;
      final int imgStarBorder = R.drawable.ic_star_border;
  
      /*get view references from content_produit_detail.xml*/
      butStar = (Button) findViewById(R.id.button_detail_heart);
  
      /*get produit class object from both Ventes.java and Location.java*/
      produit = new StackProduits();
      Intent intent = getIntent();
      produit = intent.getParcelableExtra("produit");
  
  
      /**handle favorites icon turned on or off when entering the product detail*/
      final SharedPreferences mPrefs = PreferenceManager.getDefaultSharedPreferences(this);
  
      Set&lt;String&gt; jsonList = mPrefs.getStringSet("listJson2", new HashSet&lt;String&gt;());
      Set&lt;String&gt; jsonList2 = new HashSet&lt;&gt;();
      jsonList2.addAll(jsonList);
      produit.setIsAddedAsFav("1");
      Gson gson = new Gson();
      String myJson = gson.toJson(produit);
  
      if (jsonList2.contains(myJson)) {
          butStar.setCompoundDrawablesWithIntrinsicBounds(imgStarFull, 0, 0, 0);
      } else {
          produit.setIsAddedAsFav("0");
      }
  
      /**
       * Listener for the star button used to make the current product favorite by adding it to a
       * list of all the products currently set as favorite
       */
      butStar.setOnClickListener(new View.OnClickListener() {
          @Override
          public void onClick(View v) {
              /*Change the icon and make a toast when the heart button is pressed*/
              if (produit.getIsAddedAsFav().equalsIgnoreCase("0")) {
                  produit.setIsAddedAsFav("1");
                  butStar.setCompoundDrawablesWithIntrinsicBounds(imgStarFull, 0, 0, 0);
  
                  SharedPreferences.Editor prefsEditor = mPrefs.edit();
                  Gson gson = new Gson();
  
                  //convert product to string via gson
                  String myJson = gson.toJson(produit);
                  //prefsEditor.putString("MyObject", myJson);
  
                  //get the Set&lt;String&gt; reference back to keep the entire list of favorites
                  Set&lt;String&gt; jsonList = mPrefs.getStringSet("listJson2", new HashSet&lt;String&gt;());
  
                  //make a copy of Set&lt;String&gt; pref to make it usable
                  Set&lt;String&gt; jsonList2 = new HashSet&lt;&gt;();
  
                  //add the list and the new product to the copy of Set&lt;String&gt;
                  jsonList2.addAll(jsonList);
                  jsonList2.add(myJson);
  
                  //add list to editor
                  prefsEditor.putStringSet("listJson2", jsonList2);
                  prefsEditor.apply();
                  Toast.makeText(ProduitDetail.this, getString(R.string.toast_favorite_added), Toast.LENGTH_SHORT).show();
              } else {
                  produit.setIsAddedAsFav("1");
                  butStar.setCompoundDrawablesWithIntrinsicBounds(imgStarBorder, 0, 0, 0);
                  SharedPreferences.Editor prefsEditor = mPrefs.edit();
  
                  Set&lt;String&gt; jsonList = mPrefs.getStringSet("listJson2", new HashSet&lt;String&gt;());
  
                  Set&lt;String&gt; jsonList2 = new HashSet&lt;&gt;();
                  jsonList2.addAll(jsonList);
  
                  Gson gson = new Gson();
                  String myJson = gson.toJson(produit);
  
                  jsonList2.remove(myJson);
  
                  prefsEditor.putStringSet("listJson2", jsonList2);
                  prefsEditor.apply();
                  produit.setIsAddedAsFav("0");
                  Toast.makeText(ProduitDetail.this, getString(R.string.toast_favorite_removed), Toast.LENGTH_SHORT).show();
              }
          }
      });
  }
  }
  </code></pre>
  
  <p>Here is the code of my class handling the favorites: </p>
  
  <pre><code>public class Favoris extends AppCompatActivity implements NavigationView.OnNavigationItemSelectedListener{
  
  /**fields*/
  private ListView produitFavorisListView;
  private List&lt;StackProduits&gt; listProduits = new ArrayList&lt;&gt;();
  private ProduitsAdapter adapterFavoris;
  
  @Override
  protected void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      setContentView(R.layout.activity_favoris);
  
      /*get ListView reference*/
      produitFavorisListView = (ListView) findViewById(R.id.favoritesList);
  
      /*getting back data from shared preferences*/
      final SharedPreferences mPrefs = PreferenceManager.getDefaultSharedPreferences(this);
      final Gson gson = new Gson();
  
       //getting back favorites
      Set&lt;String&gt; myJson = mPrefs.getStringSet("listJson2", new HashSet&lt;String&gt;());
  
      if (myJson.isEmpty() &amp;&amp; listProduits.isEmpty()) {
          produitFavorisListView.setAdapter(null);
      }
      else if (myJson.isEmpty() &amp;&amp; listProduits != null) {
          adapterFavoris.notifyDataSetChanged();
          adapterFavoris = new ProduitsAdapter(getApplicationContext(), -1, listProduits);
          produitFavorisListView.setAdapter(adapterFavoris);
      }
      else{
          //for each where we get back values from sting set, then convert to product
          for (String id : myJson) {
              StackProduits savedProduct = gson.fromJson(id, StackProduits.class);
              listProduits.add(savedProduct);
          }
          adapterFavoris = new ProduitsAdapter(getApplicationContext(), -1, listProduits);
          produitFavorisListView.setAdapter(adapterFavoris);
      }
  
      //Set the click listener to launch the browser when a row is clicked.
      produitFavorisListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
          @Override
          public void onItemClick(AdapterView&lt;?&gt; parent, View v, int pos, long id) {
              Intent intentProduitFavorisDetail = new Intent(Favoris.this, ProduitDetail.class);
              StackProduits ProduitFavoris = ProduitsXmlPullParser.getStackProduitFromFile(Favoris.this).get(pos);
              intentProduitFavorisDetail.putExtra("produit", ProduitFavoris);
              startActivity(intentProduitFavorisDetail);
          }
      });
  }
  }
  </code></pre>
  
  <p>Here my layout for my Favorite's ListView:</p>
  
  <pre><code>&lt;?xml version="1.0" encoding="utf-8"?&gt;
  &lt;LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  android:layout_width="match_parent"
  android:layout_height="match_parent"
  android:orientation="vertical"
  android:padding="13dp"
  android:layout_marginTop="55dp"&gt;
  
  &lt;TextView
      android:id="@+id/content_favorite_emptylist"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:text=""
      android:visibility="gone"
      android:textColor="#343232"
      android:textSize="18sp"
      android:textStyle="bold"/&gt;
  
  &lt;ListView
      android:id="@+id/favoritesList"
      android:layout_width="match_parent"
      android:layout_height="wrap_content"
      android:layout_alignParentStart="true"
      android:layout_alignParentTop="true" /&gt;
  </code></pre>
  
  <p></p>
  
  <p>Here is my adapter class:</p>
  
  <pre><code>public class ProduitsAdapter extends ArrayAdapter&lt;StackProduits&gt; {
  
  /**
   * fields
   */
  ImageLoader imageLoader;
  DisplayImageOptions options;
  List&lt;StackProduits&gt; productList;
  SparseBooleanArray mSelectedItemsIds;
  
  public ProduitsAdapter(Context ctx, int textViewResourceId, List&lt;StackProduits&gt; sites) {
      super(ctx, textViewResourceId, sites);
  
      /**Setup the ImageLoader, we'll use this to display our images*/
      ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(ctx).build();
      imageLoader = ImageLoader.getInstance();
      imageLoader.init(config);
  
      mSelectedItemsIds = new SparseBooleanArray();
  
      /**Setup options for ImageLoader so it will handle caching for us.*/
      options = new DisplayImageOptions.Builder()
              .cacheInMemory()
              .cacheOnDisc()
              .build();
  }
  
  /**
   * This method is responsible for creating row views out of a StackProduits object that can be put
   * into our ListView.
   * &lt;p/&gt;
   * (non-Javadoc)
   *
   * @see android.widget.ArrayAdapter#getView(int, android.view.View, android.view.ViewGroup)
   */
  @Override
  public View getView(int pos, View convertView, ViewGroup parent) {
      RelativeLayout row = (RelativeLayout) convertView;
      //Log.i("StackSites", "getView pos = " + pos);
      if (null == row) {   //No recycled View, we have to inflate one.
          LayoutInflater inflater = (LayoutInflater) parent.getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
          row = (RelativeLayout) inflater.inflate(R.layout.item_row, null);
      }
  
      //Get our View References from item_row.xml
      final ImageView iconImg = (ImageView) row.findViewById(R.id.iconImg);
      TextView txtDesignation = (TextView) row.findViewById(R.id.nameTxt);
      TextView txtAbout = (TextView) row.findViewById(R.id.aboutTxt);
      TextView txtPrice = (TextView) row.findViewById(R.id.priceTxt);
      TextView txtTotalArea = (TextView) row.findViewById(R.id.areaTxt);
      final ProgressBar indicator = (ProgressBar) row.findViewById(R.id.progress);
  
      //Initially we want the progress indicator visible, and the image invisible
      indicator.setVisibility(View.VISIBLE); //show progress indicator
      iconImg.setVisibility(View.INVISIBLE); //make image invisible
  
      //Setup a listener we can use to switch from the loading indicator to the Image once it's ready
      //changed ImageLoadingListener with SimpleImageLoadingListener
      SimpleImageLoadingListener listener = new SimpleImageLoadingListener() {
          @Override
          public void onLoadingStarted(String arg0, View arg1) {
              // TODO Auto-generated method stub
          }
  
          @Override
          public void onLoadingCancelled(String arg0, View arg1) {
              // TODO Auto-generated method stub
          }
  
          @Override
          public void onLoadingComplete(String arg0, View arg1, Bitmap arg2) {
              indicator.setVisibility(View.INVISIBLE);
              iconImg.setVisibility(View.VISIBLE);
          }
  
          @Override
          public void onLoadingFailed(String arg0, View arg1, FailReason arg2) {
              // TODO Auto-generated method stub
          }
      };
  
      //Load the image and use our options so caching is handled.
      imageLoader.displayImage(getItem(pos).getImgUrl(), iconImg, options, listener);
  
      //Set the relevant text in our TextViews (ListView)
      txtDesignation.setText(getItem(pos).getDesignation());
      txtAbout.setText(getItem(pos).getAbout());
      txtPrice.setText(getItem(pos).getPrice());
      txtTotalArea.setText(getItem(pos).getArea());
  
      //return view that represents the full row
      return row;
  }
  }
  </code></pre>
  
  <p>Logcat inside onItemClick (Favoris.java)</p>
  
  <pre><code>Log.i("test", adapterFavoris.getItem(pos).toString());
  
  
  07-13 13:27:27.907 1613-1613/com.example.adam_jaamour.cfimmobilier W/System: ClassLoader referenced unknown path: /data/app/com.example.adam_jaamour.cfimmobilier-2/lib/x86
  07-13 13:27:30.020 1613-1613/com.example.adam_jaamour.cfimmobilier W/System: ClassLoader referenced unknown path: /data/app/com.example.adam_jaamour.cfimmobilier-2/lib/x86
  07-13 13:27:30.169 1613-1613/com.example.adam_jaamour.cfimmobilier W/art: Before Android 4.1, method android.graphics.PorterDuffColorFilter android.support.graphics.drawable.VectorDrawableCompat.updateTintFilter(android.graphics.PorterDuffColorFilter, android.content.res.ColorStateList, android.graphics.PorterDuff$Mode) would have incorrectly overridden the package-private method in android.graphics.drawable.Drawable
  07-13 13:27:30.380 1613-1701/com.example.adam_jaamour.cfimmobilier D/OpenGLRenderer: Use EGL_SWAP_BEHAVIOR_PRESERVED: true
  
                                                                                   [ 07-13 13:27:30.388  1613: 1613 D/         ]
                                                                                   HostConnection::get() New Host Connection established 0xaa979e80, tid 1613
  
  
                                                                                   [ 07-13 13:27:30.414  1613: 1701 D/         ]
                                                                                   HostConnection::get() New Host Connection established 0xaa9796d0, tid 1701
  07-13 13:27:30.418 1613-1701/com.example.adam_jaamour.cfimmobilier I/OpenGLRenderer: Initialized EGL, version 1.4
  07-13 13:27:31.015 1613-1613/com.example.adam_jaamour.cfimmobilier I/Choreographer: Skipped 33 frames!  The application may be doing too much work on its main thread.
  07-13 13:27:32.408 1613-1613/com.example.adam_jaamour.cfimmobilier E/libEGL: call to OpenGL ES API with no current context (logged once per thread)
  07-13 13:27:32.649 1613-1701/com.example.adam_jaamour.cfimmobilier E/Surface: getSlotFromBufferLocked: unknown buffer: 0xa2329ad0
  07-13 13:27:36.071 1613-1613/com.example.adam_jaamour.cfimmobilier W/ViewRootImpl: Cancelling event due to no window focus: MotionEvent { action=ACTION_CANCEL, actionButton=0, id[0]=0, x[0]=161.13647, y[0]=1479.668, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=16698889, downTime=16695116, deviceId=0, source=0x1002 }
  07-13 13:27:36.071 1613-1613/com.example.adam_jaamour.cfimmobilier W/ViewRootImpl: Cancelling event due to no window focus: MotionEvent { action=ACTION_CANCEL, actionButton=0, id[0]=0, x[0]=161.13647, y[0]=1479.668, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=16698889, downTime=16695116, deviceId=0, source=0x1002 }
  07-13 13:27:36.072 1613-1613/com.example.adam_jaamour.cfimmobilier W/ViewRootImpl: Cancelling event due to no window focus: MotionEvent { action=ACTION_CANCEL, actionButton=0, id[0]=0, x[0]=161.13647, y[0]=1479.668, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=16698889, downTime=16695116, deviceId=0, source=0x1002 }
  07-13 13:27:36.072 1613-1613/com.example.adam_jaamour.cfimmobilier W/ViewRootImpl: Cancelling event due to no window focus: MotionEvent { action=ACTION_CANCEL, actionButton=0, id[0]=0, x[0]=161.13647, y[0]=1479.668, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=16698889, downTime=16695116, deviceId=0, source=0x1002 }
                                                                                 &lt;p&gt;&amp;nbsp;&lt;/p&gt;, reference=FFV0593, type=Apartment, numberOfRooms=Studio, livingArea=49sqm, terraceArea=-, building=Le Montaigne, district=Carré d'Or, parking=null, cellar=null, typeTransaction=Ԁt、��Fo, city=null, country=null, date created=2014-03-12 17:48:49, date last modified=2016-07-12 10:09:30]
  07-13 13:27:36.366 1613-1613/com.example.adam_jaamour.cfimmobilier W/Settings: Setting airplane_mode_on has moved from android.provider.Settings.System to android.provider.Settings.Global, returning read-only value.
  07-13 13:27:36.836 1613-1623/com.example.adam_jaamour.cfimmobilier W/art: Suspending all threads took: 12.863ms
  07-13 13:27:36.848 1613-1623/com.example.adam_jaamour.cfimmobilier I/art: Background sticky concurrent mark sweep GC freed 12227(1070KB) AllocSpace objects, 3(52KB) LOS objects, 2% free, 41MB/42MB, paused 13.974ms total 66.456ms
  07-13 13:27:36.952 1613-1619/com.example.adam_jaamour.cfimmobilier W/art: Suspending all threads took: 19.437ms
  07-13 13:27:37.062 1613-1623/com.example.adam_jaamour.cfimmobilier W/art: Suspending all threads took: 9.523ms
  07-13 13:27:37.071 1613-1623/com.example.adam_jaamour.cfimmobilier I/art: Background sticky concurrent mark sweep GC freed 2527(286KB) AllocSpace objects, 17(812KB) LOS objects, 0% free, 43MB/43MB, paused 9.952ms total 80.879ms
  07-13 13:27:37.125 1613-1701/com.example.adam_jaamour.cfimmobilier E/Surface: getSlotFromBufferLocked: unknown buffer: 0xa2329c20
  07-13 13:27:37.132 1613-1701/com.example.adam_jaamour.cfimmobilier D/OpenGLRenderer: endAllStagingAnimators on 0xa20b6880 (ListView) with handle 0xb3fec540
  </code></pre>