2

I have a recyclerview list of items and in the adapter, I have a button for adding an item as favorite to an active android database like below code:

viewholder.favoriteWP_IV.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            Favorites favorites = new Favorites(); // Model class for db crud

            favorites.setFavoritesId(UUID.randomUUID().toString());
            favorites.setLargeImgURL(pixaImages.getLargeImgURL());
            favorites.setPreviewImgURL(pixaImages.getPreviewImgURL());
            favorites.setImageId(favorites.getImageId());

            favorites.save();
            Log.d(TAG, "Fav_id:\t" + favorites.getId());
            Log.d(TAG, "Favorites Id:\t" + favorites.getFavoritesId());


            //TODO: 6/13/2018 Fix Duplicate Favorite WP
            Toast.makeText(context, "Added to Favorites", Toast.LENGTH_SHORT).show();

        }
    });

and in my FavoritesActivity, I have retrieved all the items and shown them in a recyclerview like below code:

 public List<Favorites> getAllFavorites() {
    return new Select()
            .all()
            .from(Favorites.class)
            .orderBy("favorites_id ASC")
            .execute();
}

private void getFavorites() {
    favsRV.setHasFixedSize(true);
    favsRV.setLayoutManager(new LinearLayoutManager(this));

    AdapterHeaderItem headerItem = new AdapterHeaderItem();
    headerItem.setHeaderIcon(R.drawable.drawer_header_trimmed);
    headerItem.setHeaderTitle("you can toggle through your favorite wallpapers using the wallpaper widget on your home screen");
    objectList.add(headerItem);

    //itemsList = getAllFavorites();
    Favorites favorites = new Favorites();
    for (int i = 0; i < getAllFavorites().size(); i++) {
        favorites.setFavoritesId(getAllFavorites().get(i).getFavoritesId());
        favorites.setLargeImgURL(getAllFavorites().get(i).getLargeImgURL());
        favorites.setPreviewImgURL(getAllFavorites().get(i).getPreviewImgURL());
        favorites.setImageId(getAllFavorites().get(i).getImageId());
        Log.d(TAG, "All Favs Ids:\t" + getAllFavorites().get(i).getFavoritesId());
        objectList.add(favorites);
    }
    Log.d(TAG, "Favorites List Size:\t" + objectList.size());

    adapter = new FavoritesAdapter(this, objectList);
    favsRV.setAdapter(adapter);

}

The problem here is that the item clicked on to be saved is not the one actually saved and when the list has multiple items, it retrieves duplicate copies of same item.

Previously, my adapter wasn't having a header and it was working fine but when I added the header to adapter, I had to change from List<Favorites> to List<Object> to enable me add the header items to the view.

In my activity, I have retrieved all the records while using old adapter code by this line itemsList = getAllFavorites(); but with the new adapter code, I have to use an object to store items in list.

I have tried this Favorites favs = (Favorites) itemsList = getAllFavorites(); but the app crashed, only other option I had was to do this and save in object list:

    Favorites favorites = new Favorites();
    for (int i = 0; i < getAllFavorites().size(); i++) {
        favorites.setFavoritesId(getAllFavorites().get(i).getFavoritesId());
        favorites.setLargeImgURL(getAllFavorites().get(i).getLargeImgURL());
        favorites.setPreviewImgURL(getAllFavorites().get(i).getPreviewImgURL());
        favorites.setImageId(getAllFavorites().get(i).getImageId());
        Log.d(TAG, "All Favs Ids:\t" + getAllFavorites().get(i).getFavoritesId());
        objectList.add(favorites);
    }

Here's my model class:

import com.activeandroid.Model;
import com.activeandroid.annotation.Column;
import com.activeandroid.annotation.Table;

@Table(name = "favorites")
public class Favorites extends Model{

  @Column(name = "favorites_id")
  public String favoritesId;

  @Column(name = "image_id")
  public int imageId;

  @Column(name = "large_img_url")
  public String largeImgURL;

  @Column(name = "preview_img")
  public String previewImgURL;

  public Favorites() { }

  public Favorites(String favoritesId, int imageId, String largeImgURL, String previewImgURL) {
      this.favoritesId = favoritesId;
      this.imageId = imageId;
      this.largeImgURL = largeImgURL;
      this.previewImgURL = previewImgURL;
  }

  public String getFavoritesId() {
      return favoritesId;
  }

  public void setFavoritesId(String favoritesId) {
      this.favoritesId = favoritesId;
  }

  public int getImageId() {
      return imageId;
  }

  public void setImageId(int imageId) {
      this.imageId = imageId;
  }

  public String getLargeImgURL() {
      return largeImgURL;
  }

  public void setLargeImgURL(String largeImgURL) {
      this.largeImgURL = largeImgURL;
  }

  public String getPreviewImgURL() {
      return previewImgURL;
  }

  public void setPreviewImgURL(String previewImgURL) {
      this.previewImgURL = previewImgURL;
  }
}

but this code block gives me for a list of three items, one item duplicated three times. I think it's because of the change in code. The adapter works well but in activity, I am fetching wrong results.

Here's my adapter code:

public class FavoritesAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {

private static final String TAG = FavoritesAdapter.class.getSimpleName();

private final Context context;
private List<Object> itemsList;

public static final int HEADER_VIEW = 0;
public static final int ITEMS_VIEW = 1;

public FavoritesAdapter(Context context, List<Object> itemsList) {
    this.context = context;
    this.itemsList = itemsList;
}

@NonNull
@Override
public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
    if (viewType == HEADER_VIEW) {
        View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.app_adapter_header_layout, parent, false);
        return new AdapterHeaderItemViewHolder(view);
    } else if (viewType == ITEMS_VIEW) {
        View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.favorites_item_layout, parent, false);
        return new FavoritesViewHolder(view);
    }
    throw new RuntimeException("No matching viewTypes");
}

@Override
public void onBindViewHolder(@NonNull final RecyclerView.ViewHolder holder, int position) {
    if (holder instanceof AdapterHeaderItemViewHolder) {
        AdapterHeaderItem header = (AdapterHeaderItem) itemsList.get(position);
        ((AdapterHeaderItemViewHolder) holder).headerTitleTV.setText(header.getHeaderTitle());

        Picasso.with(context)
                .load(header.getHeaderIcon())
                .placeholder(R.drawable.drawer_header_trimmed)
                .into(((AdapterHeaderItemViewHolder) holder).headerIconIV);

    } else if (holder instanceof FavoritesViewHolder) {
        final Favorites favorites = (Favorites) itemsList.get(position);

        Picasso.with(context)
                .load(favorites.getLargeImgURL())
                .placeholder(R.mipmap.ic_launcher)
                .into(((FavoritesViewHolder) holder).favoriteWPImg);

        ((FavoritesViewHolder) holder).removeTV.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Log.d(TAG, "Adapter VH Posn:\t" + holder.getAdapterPosition());

                String fav_id = favorites.getFavoritesId();
                Log.d(TAG, "Favorites+id:\t" + fav_id);
                removeAtPosition(holder.getAdapterPosition(), fav_id);
            }
        });

        ((FavoritesViewHolder) holder).previewTV.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Intent previewIntent = new Intent(context, PreviewWallPaperActivity.class);
                previewIntent.putExtra("fav_id", favorites.getFavoritesId());
                previewIntent.putExtra("large_url", favorites.getLargeImgURL());
                previewIntent.putExtra("preview_url", favorites.getPreviewImgURL());
                context.startActivity(previewIntent);
            }
        });

    }
}

private void removeAtPosition(int position, String id) {
    Log.d(TAG, "id in method:\t" + id);
    new Delete()
            .from(Favorites.class)
            .where("favorites_id=?", id)
            .execute();
    Log.d(TAG, "Favorite Removed from db");
    itemsList.remove(position);
    notifyItemRemoved(position);
    notifyItemRangeChanged(position, itemsList.size());

    Toast.makeText(context, "Removed From Favorites", Toast.LENGTH_SHORT).show();

}

@Override
public int getItemCount() {
    if (itemsList == null) {
        return 0;
    }
    return itemsList.size();
}

@Override
public int getItemViewType(int position) {
    if (isPositionHeader(position))
        return HEADER_VIEW;
    return ITEMS_VIEW;
}

private boolean isPositionHeader(int position) {
    return position == 0;
}

}

I think the problem lies here with the loop and inserting into the adapter list:

itemsList = getAllFavorites();

    Favorites favorites = new Favorites();
    for (int i = 0; i < getAllFavorites().size(); i++) {
        favorites.setFavoritesId(getAllFavorites().get(i).getFavoritesId());
        favorites.setLargeImgURL(getAllFavorites().get(i).getLargeImgURL());
        favorites.setPreviewImgURL(getAllFavorites().get(i).getPreviewImgURL());
        favorites.setImageId(getAllFavorites().get(i).getImageId());
        Log.d(TAG, "All Favs Ids:\t" + getAllFavorites().get(i).getFavoritesId());
        objectList.add(favorites);
    }

    //objectList.add(itemsList); // I have tried adding the first list of Favorite model class into the adapter list but it gives `classcast exception: Model class can't be cast to ArrayList`

Can anyone help me understand why same item is coming multiple times? Thanks.

Andromeda
  • 230
  • 1
  • 7
  • 22

0 Answers0