Search code examples
androidmysqldatabaselistviewsharedpreferences

Create favorite listview with shared preferences


I have a listview of ringtones .. I feed the list via mysql database.. (such as song names,song urls ...). I dynamically add products(ringtones) in my listview by adding new item in my database, so none of this data are inside my app except row icons.

This is the view

This is the view

As you can see I have a bookmark border icon that when user clicks on it, it will turn into selected...This is how it works :

    @Override
    public void favOnClick(int position) {
       Product product = productList.get(position);
        if (product.faved) {
            sharedPreference.addFavorite(activity,product);
            product.setFavId(R.mipmap.bookmarked);
            product.faved=false;
        }else {
            sharedPreference.removeFavorite(activity,product);
            product.setFavId(R.mipmap.bookmark_border);
            product.faved = true;
        }
        adapter.notifyDataSetChanged();  
        };

but nothing will happen in my "FAVORITES" tab .. Even the state of bookmark icon when it is selected will not be saved..

Custom Adapter

    public class FunDapter<T> extends BaseAdapter {

       public interface PlayPauseClick {
             void favOnClick(int position);
            }


       private PlayPauseClick callback;
       public void setPlayPauseClickListener(PlayPauseClick listener) {
            this.callback = listener;
        }


    protected List<T> mDataItems;
    protected List<T> mOrigDataItems;
    protected final Context mContext;
    private final int mLayoutResource;
    private final BindDictionary<T> mBindDictionary;



    public FunDapter(Context context, List<T> dataItems, int layoutResource,
                     BindDictionary<T> dictionary) {
      this(context, dataItems, layoutResource, null, dictionary);
    }


    public FunDapter(Context context, List<T> dataItems, int layoutResource,
                     LongExtractor<T> idExtractor, BindDictionary<T> dictionary) {
        this.mContext = context;
        this.mDataItems = dataItems;
        this.mOrigDataItems = dataItems;
        this.mLayoutResource = layoutResource;
        this.mBindDictionary = dictionary;
        sharedPreference = new SharedPreference();
    }



    public void updateData(List<T> dataItems) {
        this.mDataItems = dataItems;
        this.mOrigDataItems = dataItems;
        notifyDataSetChanged();
    }

    @Override
    public int getCount() {
        if (mDataItems == null || mBindDictionary == null) return 0;

        return mDataItems.size();
    }

    @Override
    public T getItem(int position) {
        return mDataItems.get(position);
    }

    @Override
    public long getItemId(int position) {
        if(idExtractor == null) return position;
        else return idExtractor.getLongValue(getItem(position), position);
    }

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

        View v = convertView;
        final GenericViewHolder holder;
        if (null == v) {
            LayoutInflater vi =
                    (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            v = vi.inflate(mLayoutResource, null);
            holder = new GenericViewHolder();
            holder.root = v;


            //init the sub views and put them in a holder instance
            FunDapterUtils.initViews(v, holder, mBindDictionary);
            v.setTag(holder);
            }else {
            holder = (GenericViewHolder) v.getTag();
            }

        final T item = getItem(position);
        showData(item, holder, position);

        Product product = (Product) mDataItems.get(position);
        holder.favImage=(ImageView)v.findViewById(R.id.favImage); 
        holder.favImage.setImageResource(product.getFavId());
        holder.favImage.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

                if (callback != null) {
                      callback.favOnClick(position);
                    } 
            }
        }); 


        return v;
    }

}

Product model class

    @SuppressWarnings("serial")
public class Product implements Serializable {
    @SerializedName("pid")
    public int pid;

    @SerializedName("name")
    public String name;

    @SerializedName("qty")
    public int qty;

    @SerializedName("price")
    public String description;

    @SerializedName("song_url")
    public String song_url;

    @SerializedName("date")
    public String date;


    public boolean paused = true;
    public boolean faved = true;

     private int favId;
    public int getFavId() {
        return favId;}
    public void setFavId(int favId) {
        this.favId = favId;} 
}

SharedPreferences class

   public class SharedPreference {

    public static final String PREFS_NAME = "PRODUCT_APP";
    public static final String FAVORITES = "Product_Favorite";

    public SharedPreference() {
        super();
    }

    // This four methods are used for maintaining favorites.
    public void saveFavorites(Context context, List<Product> favorites) {
        SharedPreferences settings;
        Editor editor;
        settings = context.getSharedPreferences(PREFS_NAME,Context.MODE_PRIVATE);
        editor = settings.edit();
        Gson gson = new Gson();
        String jsonFavorites = gson.toJson(favorites);
        editor.putString(FAVORITES, jsonFavorites);
        editor.commit();
    }

    public void addFavorite(Context context, Product product) {
        List<Product> favorites = getFavorites(context);
        if (favorites == null)
            favorites = new ArrayList<Product>();
            favorites.add(product);
            saveFavorites(context, favorites);
    }

    public void removeFavorite(Context context, Product product) {
        ArrayList<Product> favorites = getFavorites(context);
        if (favorites != null) {
            favorites.remove(product);
            saveFavorites(context, favorites);
        }
    }

    public ArrayList<Product> getFavorites(Context context) {
        SharedPreferences settings;
        List<Product> favorites;
        settings = context.getSharedPreferences(PREFS_NAME,Context.MODE_PRIVATE);
        if (settings.contains(FAVORITES)) {
            String jsonFavorites = settings.getString(FAVORITES, null);
            Gson gson = new Gson();
            Product[] favoriteItems = gson.fromJson(jsonFavorites,Product[].class);
            favorites = Arrays.asList(favoriteItems);
            favorites = new ArrayList<Product>(favorites);
        } else
            return null;

        return (ArrayList<Product>) favorites;
    }
}

I'm stuck here for a few days, Can you help me please !

This is my project link if you would like to look into it for further info

http://symphonyrecords.ir/RingtoneApp.rar


Solution

  • There are two problems here (based on your project)

    First (saving state of bookmark Imageview)

    In adapter create a method that checks whether a particular product exists in SharedPreferences

        public boolean checkFavoriteItem(Product checkProduct) {
        boolean check = false;
        List<Product> favorites = sharedPreference.getFavorites(null, mContext);
        if (favorites != null) {
            for (Product product : favorites) {
                if (product.equals(checkProduct)) {
                    check = true;
                    break;
                }
            }
        }
        return check;
    }
    

    Inside adapter check if a product exists in shared preferences then set bookmarked drawable and set a tag

    if (checkFavoriteItem(product)) {
            holder.favoriteImg.setImageResource(R.mipmap.bookmarked);
            holder.favoriteImg.setTag("bookmarked");
        } else {
            holder.favoriteImg.setImageResource(R.mipmap.bookmark_border);
            holder.favoriteImg.setTag("bookmark_border");
        }
    

    Then inside favOnClick callback method

        @Override
        public boolean favOnClick(int position ,View v) {
            Product product = (Product) productList.get(position);
            ImageView button = (ImageView) v.findViewById(R.id.favImage);
            String tag = button.getTag().toString();
            if (tag.equalsIgnoreCase("bookmark_border")) {
                sharedPreference.addFavorite(activity,product);
                Toast.makeText(activity,"Added to Favorites",Toast.LENGTH_SHORT).show();
                button.setTag("bookmarked");
                button.setImageResource(R.mipmap.bookmarked);
            } else {
                sharedPreference.removeFavorite(activity,product);
                button.setTag("bookmark_border");
                button.setImageResource(R.mipmap.bookmark_border);
                Toast.makeText(activity,"Removed from Favorites",Toast.LENGTH_SHORT).show();
            }
            return true;
            }
    

    Second (get favorite product and pass it to "FAVORITE" Fragment)

    Inside getFavorite method add a String parameter Then in your "FAVORITE" Fragment with processFinish(your AsyncResponse) call your getFavorite in order to get your Favorite product list then set your adapter :

    Context mContext;
    `mContext = getContext();`
    
    @Override
    public void  processFinish(String s) {
        productList = sharedPreference.getFavorites(s, mContext);
    
        BindDictionary<Product> dict = new BindDictionary<Product>();
        dict.addStringField(R.id.tvName, new StringExtractor<Product>() {
            @Override
            public String getStringValue(Product product, int position) {
                return product.name;
            }
        });
    
    
        dict.addStringField(R.id.tvDescription, new StringExtractor<Product>() {
            @Override
            public String getStringValue(Product product, int position) {
                return product.description;
    
            }
        });
    
    
        dict.addStringField(R.id.tvQty, new StringExtractor<Product>() {
            @Override
            public String getStringValue(Product product, int position) {
                return "" + product.qty;
    
            }
        });
    
    
        adapter = new FunDapter<>(getActivity(), productList, R.layout.d_layout_list_d, dict);
        lvProduct.setAdapter(adapter);
    
    }