Favorite fragment using SharedPreference - android

I'm adding a favorite button to my android application that saves pharmacies
in a fragment using SharedPreference and i get this error "Unreachable statement" in the line where i change the color of the button favorite whene it's clicked
if (checkFavoriteItem(pharmacie)) {
holder.img_favorite.setImageResource(R.drawable.heart_red); /********error*********/
holder.img_favorite.setTag("red");
} else {
holder.img_favorite.setImageResource(R.drawable.heart_grey);
holder.img_favorite.setTag("grey");
}
return convertView;}
this is the full PharmacyArrayAdapter activity:
public class PharmacyArrayAdapterfav extends ArrayAdapter<Pharmacie> {
Context myContext;
int layoutResourceId;
List<Pharmacie> pharmacie;
SharedPreference sharedPreference;
private Context context;
public PharmacyArrayAdapterfav(Context context, List<Pharmacie> pharmacie) {
super(context, R.layout.liste_layout, pharmacie);
this.context = context;
this.pharmacie = pharmacie;
myContext=context;
sharedPreference = new SharedPreference();
}
private class ViewHolder {
TextView nomTextView;
TextView villeTextView;
ImageView img_favorite;
TextView lonTextView;
}
#Override
public int getCount() {
return pharmacie.size();
}
#Override
public Pharmacie getItem(int position) {
return pharmacie.get(position);
}
#Override
public long getItemId(int position) {
return 0;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
//return super.getView(position, convertView, parent);
ViewHolder holder = null;
if (convertView == null) {
LayoutInflater inflater = (LayoutInflater) context
.getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
convertView = inflater.inflate(R.layout.fragment_product_list, null);
holder = new ViewHolder();
holder.nomTextView = (TextView) convertView
.findViewById(R.id.textViewNom);
holder.villeTextView = (TextView) convertView
.findViewById(R.id.txtViewVille);
holder.img_favorite = (ImageView) convertView
.findViewById(R.id.img_favorite);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
Pharmacie pharmacie = (Pharmacie) getItem(position);
holder.nomTextView.setText(pharmacie.getNom());
holder.villeTextView.setText(pharmacie.getVille());
return convertView;
if (checkFavoriteItem(pharmacie)) {
holder.img_favorite.setImageResource(R.drawable.heart_red);
holder.img_favorite.setTag("red");
} else {
holder.img_favorite.setImageResource(R.drawable.heart_grey);
holder.img_favorite.setTag("grey");
}
return convertView;}
/*Checks whether a particular product exists in SharedPreferences*/
public boolean checkFavoriteItem(Pharmacie checkProduct) {
boolean check = false;
List<Pharmacie> favorites = sharedPreference.getFavorites(context);
if (favorites != null) {
for (Pharmacie product : favorites) {
if (product.equals(checkProduct)) {
check = true;
break;
}
}
}
return check;
}
#Override
public void add(Pharmacie phar) {
super.add(phar);
pharmacie.add(phar);
notifyDataSetChanged();
}
#Override
public void remove(Pharmacie phar) {
super.remove(phar);
pharmacie.remove(phar);
notifyDataSetChanged();
}
}
And also i want to know how to save the list to a specific user that finds his list of favorites after he logs in and clicks favorites button ,please i need help, thank you.

Oh my god, I totally didn't see a very obvious reason why you have unreachable code - you have an extra return that shouldn't be there:
Pharmacie pharmacie = (Pharmacie) getItem(position);
holder.nomTextView.setText(pharmacie.getNom());
holder.villeTextView.setText(pharmacie.getVille());
return convertView; //THIS ONE -> just remove it and it'll work
if (checkFavoriteItem(pharmacie)) {
holder.img_favorite.setImageResource(R.drawable.heart_red);
holder.img_favorite.setTag("red");
} else {
holder.img_favorite.setImageResource(R.drawable.heart_grey);
holder.img_favorite.setTag("grey");
}
return convertView;
}
Unreachable code warning is usually this^, having a return that is not in an if branch and some code after it, it means that the method will always return at that point and will never run the code below it. It's not an error per se, it's just IDE warning you that you might have mistakenly put return where you didn't mean to.

Related

Android Listview is repeating items when scrolled

I have looked at other threads and I cannot see what is wrong with my listadapter. I have the view holder pattern and I am setting all the values for the list item outside of the convertview null check statement. Im not sure what other things would cause it to repeat the items.
public class ScheduledJobListAdapter extends BaseAdapter {
private static LayoutInflater inflater = null;
private ArrayList<Job> jobList;
private Context context;
public ScheduledJobListAdapter(Context context, ArrayList<Job> jobList) {
this.context = context;
this.jobList = jobList;
inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
#Override
public int getCount() { return jobList.size(); }
#Override
public Job getItem(int position) { return jobList.get(position); }
#Override
public long getItemId(int position) { return 0; }
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
final ScheduledViewHolder holder;
if (convertView == null) {
convertView = inflater.inflate(R.layout.list_item_scheduled_job,null);
holder = new ScheduledViewHolder();
holder.job = getItem(position);
holder.container = convertView.findViewById(R.id.scheduled_job_layout);
holder.routeOrder = convertView.findViewById(R.id.route_order_textview);
holder.location = convertView.findViewById(R.id.location_textview);
holder.jobRef = convertView.findViewById(R.id.job_ref_textview);
holder.statusIndicator = convertView.findViewById(R.id.status_indicator);
convertView.setTag(holder);
} else {
holder = (ScheduledViewHolder) convertView.getTag();
}
holder.routeOrder.setText(holder.job.getRouteOrder() + "");
holder.location.setText(holder.job.getLocation());
holder.jobRef.setText(holder.job.getJobReference());
return convertView;
}
}
class ScheduledViewHolder {
Job job;
LinearLayout container;
TextView routeOrder;
TextView location;
TextView jobRef;
ImageView statusIndicator;
}
Here's the problem:
holder.job = getItem(position);
Remember the views may be recycled as you scroll, and the job assigned maybe used unintentionally for other positions if you assigned it that way. To fix it, simply assign the job after the if-else condition:
if (convertView == null) {
// ...
} else {
// ...
}
holder.job = getItem(position); // Update the job by position
holder.routeOrder.setText(holder.job.getRouteOrder() + "");
holder.location.setText(holder.job.getLocation());
holder.jobRef.setText(holder.job.getJobReference());

boolean variable unavailable in getView()

I never understand the getView() method fully. Here is a case:
Here I have isNoticeRead which is false you can see. But the line gets executed! And when the line in the if statement is executing, isNoticeRead is not found anywhere! If I even place my cursor over it, nothing happens (no tooltip). And it happens for the first item of the ListView. Can you please tell me what am I missing?
My full Adapter
public class NoticesListViewAdapter extends BaseAdapter{
Context context;
ArrayList<NoticeModel> items;
String[] readNotices;
public NoticesListViewAdapter(Context context, ArrayList<NoticeModel> items) {
this.context = context;
this.items = items;
readNotices = SharedPrefUtils.getMarkedNotices(context).split(SharedPrefUtils.SEPARATOR_READ_NOTICE);
}
#Override
public int getCount() {
return items.size();
}
#Override
public Object getItem(int position) {
return items.get(position);
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
Holder holder;
if(convertView == null){
convertView = LayoutInflater.from(context).inflate(R.layout.list_item_notices, null);
holder = new Holder();
holder.noticeID = (TextView) convertView.findViewById(R.id.noticeID);
holder.tvNotice = (TextView) convertView.findViewById(R.id.tvNotice);
holder.tvDateTime = (TextView) convertView.findViewById(R.id.tvDateTime);
holder.tvNoticeRead = (TextView) convertView.findViewById(R.id.tvNoticeRead);
convertView.setTag(holder);
}else{
holder = (Holder) convertView.getTag();
}
try {
String str = items.get(position).getId() + "";
holder.noticeID.setText(str);
holder.tvNotice.setText(items.get(position).getText());
holder.tvDateTime.setText(DateTimeUtils.changeDateTimeFormat(items.get(position).getDateTime(), DateTimeUtils.FORMAT8, DateTimeUtils.FORMAT3));
final boolean isNoticeRead = items.get(position).isRead();
if (isNoticeRead) {
holder.tvNoticeRead.setVisibility(View.VISIBLE);
}
// for(String s : readNotices) {
// if (s.equals(str)) {
// holder.tvNoticeRead.setVisibility(View.VISIBLE);
//// break;
// }
// }
}catch (Exception e){e.printStackTrace();}
return convertView;
}
class Holder{
TextView tvNotice, tvDateTime, noticeID, tvNoticeRead;
}
}
The views of your holder are being re-used by the List. Thus you may have an instance which is initialized with VISIBLE, but when the view is reused and filled, you don't reset its state - so it is still visible.
if (isNoticeRead) {
holder.tvNoticeRead.setVisibility(View.VISIBLE);
} else {
holder.tvNoticeRead.setVisibility(View.INVISIBLE);
}
when you make variable final then it's means unable to assigned value during execute because you make it final remove final or define isNoticeRead as field.
then it may be work fine for you..

notifyDatasetChanged is not working inside the getView() method for Custom Adapter In Android

I am basically trying hide and show a text in the list row when I am clicking a button in the list row. I have added the onClick() for the button inside getView() method and then calling the notifyDataSetChanged(). But it is not working. No change in the text visibility. Here is my custom Adapter code:
public class ListAdapter extends BaseAdapter {
private Context context;
private List<String> mListQuestion = null;
private List<String> mListAnswer = null;
ViewHolder holder = null;
boolean flag = false;
public ListAdapter(Context context, List<String> question, List<String> answer ) {
this.mListQuestion = question;
this.mListAnswer = answer;
this.context = context;
}
#Override
public Object getItem(int position)
{
return mListQuestion.get(position);
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public int getCount() {
return mListQuestion.size();
}
#Override
#SuppressWarnings("deprecation")
public View getView(int position, View convertView, ViewGroup parent) {
if (convertView == null)
{
LayoutInflater vi = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = vi.inflate(R.layout.list_faq_item, null);
holder = new ViewHolder();
holder.tvQuestion = (TextView) convertView.findViewById(R.id.text);
holder.tvAns = (TextView) convertView.findViewById(R.id.anstext);
holder.ivArrow = (Button)convertView.findViewById(R.id.arrow_expand);
convertView.setTag(holder);
}
else
{
holder = (ViewHolder) convertView.getTag();
}
holder.tvQuestion.setText(mListQuestion.get(position));
holder.tvAns.setText(mListAnswer.get(position));
holder.ivArrow.setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(View v)
{
if (flag == false)
{
Logger.d("arrow clicked when flag is false");
holder.tvAns.setVisibility(View.VISIBLE);
holder.ivArrow.setBackgroundResource(R.drawable.up_arrow);
flag = true;
}
else if (flag == true)
{
Logger.d("arrow clicked when flag is true");
holder.tvAns.setVisibility(View.GONE);
holder.ivArrow.setBackgroundResource(R.drawable.down_arrow);
flag = false;
}
notifyDataSetChanged();
}
});
return convertView;
}
static class ViewHolder {
TextView tvQuestion;
TextView tvAns;
Button ivArrow;
}
}
Can someone please tell what I am doing wrong here.
Thanks in Advance.
-Arindam.
public class ListAdapter extends BaseAdapter {
private Context context;
private List<String> mListQuestion = null;
private List<String> mListAnswer = null;
ViewHolder holder = null;
private List<Boolean> textViewVisibileState;
public ListAdapter(Context context, List<String> question, List<String> answer ) {
this.mListQuestion = question;
this.mListAnswer = answer;
this.context = context;
this.textViewVisibileState=new ArrayList<>(Arrays.asList(new Boolean[getCount()]));
Collections.fill(this.textViewVisibileState,false);
}
#Override
public Object getItem(int position)
{
return mListQuestion.get(position);
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public int getCount() {
return mListQuestion.size();
}
#Override
#SuppressWarnings("deprecation")
public View getView(int position, View convertView, ViewGroup parent) {
if (convertView == null)
{
LayoutInflater vi = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = vi.inflate(R.layout.list_faq_item, null);
holder = new ViewHolder();
holder.tvQuestion = (TextView) convertView.findViewById(R.id.text);
holder.tvAns = (TextView) convertView.findViewById(R.id.anstext);
holder.ivArrow = (Button)convertView.findViewById(R.id.arrow_expand);
convertView.setTag(holder);
}
else
{
holder = (ViewHolder) convertView.getTag();
}
holder.tvQuestion.setText(mListQuestion.get(position));
holder.tvAns.setText(mListAnswer.get(position));
if(textViewVisibileState.get(position))
{
holder.tvAns.setVisibility(View.GONE);
holder.ivArrow.setBackgroundResource(R.drawable.down_arrow);
}
else
{
Logger.d("arrow clicked when flag is false");
holder.tvAns.setVisibility(View.VISIBLE);
holder.ivArrow.setBackgroundResource(R.drawable.up_arrow);
}
holder.ivArrow.setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(View v)
{
if (textViewVisibileState.get(position))
{
textViewVisibileState.set(position,false);
}
else
{
textViewVisibileState.set(position,true);
}
notifyDataSetChanged();
}
});
return convertView;
}
static class ViewHolder {
TextView tvQuestion;
TextView tvAns;
Button ivArrow;
}
}
This will work.
The variable flag is not context sensitive to object holder. So flag is always = false in your case. How about setVisibility(View.GONE) initially? And then setVisibility(View.VISIBLE) ONLY when ivArrow is clicked upon.
Calling notifyDataSetChanged() causes ListView to rebuild everything. It will remove its child views, call getView() for all the items that are visible, and thus you will rebind all the data for those items.
But your data hasn't actually changed. You haven't modified anything in the questions list, so binding the data again is meaningless. Instead you have tried to change something in your ViewHolder object, but there's no guarantee that the convertView you get after a notifyDataSetChanged() is for the same position as before, so it's possible that some other item has been affected (or perhaps none at all?).
Try removing the call to notifyDataSetChanged() from the OnClickListener. A visibility change should cause a re-layout of the view hierarchy, but as long as you haven't told ListView that the data has changed, it should keep all its current children.
Create an instance of the adapter, e.g Adapter myAdapter = new Adapter, set it to a listview or recyclerview e.g listview.setAdapter(mydapter) and everytime you add new data to it call adapter.notifyDataSetChanged()

Android Base Adapter

I am adding multiple UI elements like SeekBar,ImageView,TextView dynamically to the ListView.But Whenever I try to get the reference to these elements,I am always getting reference to the last element only.
e.g I have multiple SeekBar.When i press play button that SeekBar should update.But the problem is when i press any number of play button only SeekBar at last position is getting updated.
I tried
seekbar.setTag(position);
But of no use.
Finally the solution is, I made my ViewHolder class's object local inside getView() method and assigned it to a global ViewHolder class's object on play button's OnClickListener.This change solved my problem like a miracle.
The tag you are setting should be instance of your ViewHolder class.
Your code can be like this -
public class YourTeamAdapter extends BaseAdapter {
private static Context context;
private ArrayList<TopDataModel> mList;
public YourTeamAdapter(Context c, ArrayList<TopDataModel> list) {
mList = list;
context = c;
}
#Override
public int getCount() {
return mList.size();
}
// get item at givin position
#Override
public TopDataModel getItem(int position) {
return mList.get(position);
}
// get itemID at givin position
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
Holder holder = null;
if (convertView == null) {
LayoutInflater inflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = inflater.inflate(R.layout.activity_team_status_list_item, null, true);
holder = new Holder(convertView);
convertView.setTag(holder);
} else {
holder = (Holder) convertView.getTag();
}
holder.tvName.setText(getItem(position).getName());
holder.tvRank.setText(getItem(position).getRank());
try {
if (getItem(position).getImage() != null &&
!getItem(position).getImage().equalsIgnoreCase("")) {
holder.imageView.setImageBitmap(SharedHelper.decodeBase64(getItem(position).getImage()));
}
} catch (Exception e) {
e.printStackTrace();
}
return convertView;
}
private static class Holder {
TextView tvName;
TextView tvRank;
CircularImageView imageView;
public Holder(View convertView) {
this.tvName = (TextView) convertView.findViewById(R.id.name);
this.tvRank = (TextView) convertView.findViewById(R.id.rank);
this.imageView = (CircularImageView) convertView.findViewById(R.id.image);
}
}
}

Android Baseadapter fixed blankfields

I have got a problem with my BaseAdapter. I am using a Gridview to show my content. And i need to add some blankfield.
But if i scroll up and down the blankfields move randomly.
My Question is: How can i make them stay at the right position?
public class GridviewAdapter extends BaseAdapter {
private ArrayList<String> sign;
private ArrayList<String> roman;
private ArrayList<String> check;
private Activity activity;
private int minusValue=0;
private boolean fulllist;
public GridviewAdapter(Activity activity, ArrayList<String> sign,ArrayList<String> roman,ArrayList<String> check,boolean fulllist) {
super();
this.activity=activity;
this.sign=sign;
this.roman=roman;
this.check=check;
this.fulllist=fulllist;
}
#Override
public int getCount() {
if(fulllist)
{
return sign.size()+5;
}
else
{
return sign.size();
}
}
public void updateList(ArrayList<String> newcheck) {
check.clear();
check.addAll(newcheck);
this.notifyDataSetChanged();
}
#Override
public Object getItem(int position) {
return sign.get(position);
}
#Override
public long getItemId(int position) {
return position;
}
public static class ViewHolder
{
public TextView signv;
public TextView romanv;
public TextView checkv;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder view= new ViewHolder();
LayoutInflater inflator = activity.getLayoutInflater();
if (convertView == null) {
view = new ViewHolder();
convertView = inflator.inflate(R.layout.gridblock, null);
view.signv = (TextView) convertView.findViewById(R.id.sign);
view.checkv = (TextView) convertView.findViewById(R.id.check);
view.romanv = (TextView) convertView.findViewById(R.id.roman);
convertView.setTag(view);
} else {
view = (ViewHolder) convertView.getTag();
}
if(position==36) {
convertView.setVisibility(View.GONE);
convertView.setClickable(false);
convertView.setEnabled(false);
minusValue=minusValue-1;
}
else if(position==38) {
convertView.setVisibility(View.GONE);
convertView.setClickable(false);
convertView.setEnabled(false);
minusValue=minusValue-1;
}
else if(position==46) {
convertView.setVisibility(View.GONE);
convertView.setClickable(false);
convertView.setEnabled(false);
minusValue=minusValue-1;
}
else if(position==47) {
convertView.setVisibility(View.GONE);
convertView.setClickable(false);
convertView.setEnabled(false);
minusValue=minusValue-1;
}
else if(position==48) {
convertView.setVisibility(View.GONE);
convertView.setClickable(false);
convertView.setEnabled(false);
minusValue=minusValue-1;
}
else
{
view.signv.setText(sign.get(0));
view.checkv.setText(check.get(0));
if( view.checkv.getText().equals("✘"))
{
view.checkv.setTextColor(Color.RED);
}
else
{
view.checkv.setTextColor(Color.GREEN);
}
view.romanv.setText(roman.get(0));
}
return convertView;
}
In the else clause, when updating all the ViewHolder fields, you need to undo the invisibility applied for the blank positions. Eg:
convertView.setVisibility(View.VISIBLE);
convertView.setClickable(true);
convertView.setEnabled(true);
This is because recycled views are not guaranteed to be the same position as when they were initially inflated. Meaning the view used for position 47 may be reused for position 2.
I'm not sure what you are doing with the minusValue but you may need to adjust that as well. Keep in mind, getView() can and will be called 3-4 times per position number. Just an FYI when using that variable.

Categories

Resources