button text disappears when scrolling or adding and item in listview, Android

I'm having an issue with a list view I'm using. Each item in the listview has two buttons that users can use to add or take away points from each contestant.

The issue is when I add a new item to the list view or when scrolling (after having added at least one item) the code randomly takes the text out of the buttons on one or more of the items.

Can any one tell me A) what is causing this? and B) how to solve it?

I've included what I believe to be the relevant code. Let me know if you think I need to put some more up here.

My adapter class:

public class ContestantListAdapter extends BaseAdapter {
private ArrayList<ContestantItem> contestantList;
private LayoutInflater  layoutInflater;

public ContestantListAdapter(Context context, ArrayList<ContestantItem> contestantList){
    this.contestantList = contestantList;
    layoutInflater = LayoutInflater.from(context);
}
@Override
public int getCount(){
    return contestantList.size();
}
public View getView(int position, View convertView, ViewGroup parentView){
    ViewHolder viewHolder;
    if(convertView == null){
        convertView = layoutInflater.inflate(R.layout.contestant_row_layout,null);//null might need to be activity_main
        viewHolder = new ViewHolder();
        viewHolder.nameView = (TextView) convertView.findViewById(R.id.nameView);
        viewHolder.pointsView = (TextView) convertView.findViewById(R.id.pointsView);
        convertView.setTag(viewHolder);
    }else{
        viewHolder = (ViewHolder)convertView.getTag();
    }
    viewHolder.nameView.setText((contestantList.get(position).getName()));
    viewHolder.pointsView.setText(Integer.toString(contestantList.get(position).getPoints()));

    //get button position
    Button button =(Button) convertView.findViewById(R.id.Minus);
    button.setOnClickListener(minusListener);
    Button buttonPlus = (Button) convertView.findViewById(R.id.Plus);
    buttonPlus.setOnClickListener(addListener);
    return convertView;
}

private View.OnClickListener minusListener = new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        View parentRow = (View) v.getParent();
        ListView listView = (ListView) parentRow.getParent();
        final int position = listView.getPositionForView(parentRow);
        ContestantItem tmpContestant = (ContestantItem) contestantList.get(position);
        int tmpPoints = tmpContestant.getPoints()-1;
        if(tmpPoints<0){tmpPoints=0;}
        tmpContestant.setPoints(tmpPoints);
        notifyDataSetChanged();
    }
};
private View.OnClickListener addListener = new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        View parentRow = (View) v.getParent();
        ListView listView = (ListView) parentRow.getParent();
        final int position = listView.getPositionForView(parentRow);
        ContestantItem tmpContestant = (ContestantItem) contestantList.get(position);
        int tmpPoints = tmpContestant.getPoints()+1;
        tmpContestant.setPoints(tmpPoints);
        notifyDataSetChanged();
    }
};
static class ViewHolder {
    TextView nameView;
    TextView pointsView;
}
@Override
public Object getItem(int index){
    return contestantList.get(index);
}
@Override
public long getItemId(int index){
    return index;
}

//this method should add the contestent to the listView.  must know what position to add it in.
public void addItem(String name, int index){
    ContestantItem tempContestant = new ContestantItem();
    tempContestant.setName(name);
    tempContestant.setPoints(1);
    contestantList.add(index,tempContestant);
    notifyDataSetChanged();
}
. . .

ContestantRowLayout:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="match_parent">

<Button
android:layout_width="0dp"
android:layout_height="50dp"
    android:layout_weight="0.15"
android:id="@+id/Minus"
android:text="@string/minus"
/>

<TextView
    android:layout_width="0dp"
    android:layout_height="50dp"
    android:layout_weight="0.5"
    android:id="@+id/nameView"
    />

<TextView
    android:layout_width="0dp"
    android:layout_height="50dp"
    android:layout_weight="0.2"
    android:id="@+id/pointsView"
    />


<Button
    android:layout_width="0dp"
    android:layout_height="50dp"
    android:layout_weight="0.15"
    android:id="@+id/Plus"
    android:text="@string/plus"
    />

</LinearLayout>

Main Activity:

public class MainActivity extends AppCompatActivity implements                           ContestantsFragment.OnFragmentInteractionListener{

ListView listView1;
ContestantListAdapter contestantAdapter;

@Override
protected void onCreate(Bundle savedInstanceState){
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    ArrayList<ContestantItem> rowDetails = getListData();

    listView1 = (ListView) findViewById(R.id.contactsListView);
    listView1.setAdapter(new ContestantListAdapter(this,rowDetails));
    contestantAdapter = (ContestantListAdapter) listView1.getAdapter();

}

private ArrayList getListData(){
    ArrayList<ContestantItem> contestantList = new ArrayList<ContestantItem>();
    ContestantItem cItem;
    for(int i=0;i<10;i++){
        cItem = new ContestantItem();
        cItem.setName("Danny Anderson");
        cItem.setPoints(5);
        contestantList.add(cItem);
    }
    return contestantList;
}

@Override
public void onFragmentInteraction(Uri uri) {

}
//if the name is found returns the index position in the list.  If not found -99
public void findAlphabetical(View view){
    //TODO implement Binary search algorithm.
    hideKeyboard();
    EditText tmpEditTxt = (EditText) findViewById(R.id.searchField);
    String inputTxt = tmpEditTxt.getText().toString();
    int findAtIndex =contestantAdapter.searchAlphabetical(inputTxt)-1;
    if(findAtIndex <0){findAtIndex=0;}
    listView1.smoothScrollToPosition(findAtIndex);
}
public void addInAlpabetOrder(View view){
    //TODO  add the name in alphabetical order
    hideKeyboard();
    //ListView tmpListView = (ListView) contestantsFragment.getView().findViewById(R.id.contactsListView);
    EditText tmpEditTxt = (EditText) findViewById(R.id.searchField);
    String inputTxt = tmpEditTxt.getText().toString();
    int addAtIndex =contestantAdapter.searchAlphabetical(inputTxt);
    contestantAdapter.addItem(inputTxt, addAtIndex);
    listView1.smoothScrollToPosition(addAtIndex);
}
public void clearContestantList(View view){
    //TODO clear out all contestants from the list
    contestantAdapter.clearAllItems();

}
. . .

Answers


I am mentioning what @Suhas Bachewar has said and putting something together with code you have, as you should know that you are using a recycler to get your view populated with different object in the list, why not have the click events inside getView like that you don't have to do the hustle for looking for which particular button view is associated to a object whose value has to be increased,

public View getView(int position, View convertView, ViewGroup parentView){
    ViewHolder viewHolder;
    if(convertView == null){
        convertView = layoutInflater.inflate(R.layout.contestant_row_layout,null);//null might need to be activity_main
        viewHolder = new ViewHolder();
        viewHolder.nameView = (TextView) convertView.findViewById(R.id.nameView);
        viewHolder.buttonMinus= (Button) convertView.findViewById(R.id.Minus);
        viewHolder.buttonPlus= (Button) convertView.findViewById(R.id.Plus);
        viewHolder.pointsView = (TextView) convertView.findViewById(R.id.pointsView);
        convertView.setTag(viewHolder);
    }else{
        viewHolder = (ViewHolder)convertView.getTag();
    }
    viewHolder.nameView.setText((contestantList.get(position).getName()));
    viewHolder.pointsView.setText(Integer.toString(contestantList.get(position).getPoints()));

    //get button position

    buttonMinus.setOnClickListener(minusListener);

    buttonPlus.setOnClickListener(addListener);
    return convertView;
}

private View.OnClickListener minusListener = new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        View parentRow = (View) v.getParent();
        ListView listView = (ListView) parentRow.getParent();
        final int position = listView.getPositionForView(parentRow);
        ContestantItem tmpContestant = (ContestantItem) contestantList.get(position);
        int tmpPoints = tmpContestant.getPoints()-1;
        if(tmpPoints<0){tmpPoints=0;}
        tmpContestant.setPoints(tmpPoints);
        notifyDataSetChanged();
    }
};
private View.OnClickListener addListener = new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        View parentRow = (View) v.getParent();
        ListView listView = (ListView) parentRow.getParent();
        final int position = listView.getPositionForView(parentRow);
        ContestantItem tmpContestant = (ContestantItem) contestantList.get(position);
        int tmpPoints = tmpContestant.getPoints()+1;
        tmpContestant.setPoints(tmpPoints);
        notifyDataSetChanged();
    }
};
static class ViewHolder {
    TextView nameView;
    TextView pointsView;
    Button buttonMinus;
    Button buttonPlus;
}

Need Your Help

Wrong Thread.CurrentPrincipal in async WCF end-method

wcf async-await wif iprincipal executioncontext

I have a WCF service which has its Thread.CurrentPrincipal set in the ServiceConfiguration.ClaimsAuthorizationManager.