0

I have created a custom list which has a card view, button , text view and a switch. I have set tag to the card view.

But when I tried to retrieve this tag in table view holder it's throwing a null pointer exception.

If I get the tag inside a listener it dose not throw any exception. I don't know from where to access this tag.

I want to do setChecked true for switch if the status is one and setChecked should be false if the status is 0.

But I don't get where to do this?

CustomAlertAdapter

public class TableListAdapter extends RecyclerView.Adapter<TableListAdapter.TableViewHolder> {


    public static TimeTableHelper db;
    public static TimeTableList timeTableList;

    public static int cardId,id,status=0;
    public static boolean editMode;
    public static List<TimeTable> tableList;
    public static TimeTable t = new TimeTable();
    public static TimeTable ci;

    public TableListAdapter(List<TimeTable> tableList,TimeTableList timeTableList) {
        this.tableList = tableList;
        this.timeTableList = timeTableList;
    }
    private Context context;

    public TableListAdapter(Context context) {
        this.context = context;
    }
    @Override
    public int getItemCount() {
          return tableList.size();
    }

    @Override
    public void onBindViewHolder(TableViewHolder tableViewHolder, int i) {


        ci = tableList.get(i);

        tableViewHolder.cv.setTag(i);

        tableViewHolder.aSwitch.setTag(i);

        Log.d("setId", String.valueOf(i));
        tableViewHolder.tableTitle.setText(ci.getTitle());

        ((GradientDrawable)tableViewHolder.color.getBackground()).setColor(ci.getTableColor());



    }

   @Override
   public TableViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {

        View  itemView = LayoutInflater.
                   from(viewGroup.getContext()).
                   inflate(R.layout.table_card, viewGroup, false);


       return new TableViewHolder(itemView);
   }

  public static class TableViewHolder extends RecyclerView.ViewHolder {

      protected TextView tableTitle;
      protected CardView cv;
      protected SwitchCompat aSwitch;
      protected Button color;


      public TableViewHolder(final View v) {
          super(v);
          tableTitle = (TextView) v.findViewById(R.id.tableTitle);
          cv = (CardView) v.findViewById(R.id.card_view);
          aSwitch = (SwitchCompat) v.findViewById(R.id.switch2);
          color = (Button) v.findViewById(R.id.selectColor);

          db = new TimeTableHelper(timeTableList);


          cv.setOnLongClickListener(new View.OnLongClickListener() {

              @Override
              public boolean onLongClick(final View v) {
                  // TODO Auto-generated method stub

                  final AlertDialog.Builder builder = new AlertDialog.Builder(timeTableList);

                  builder.setTitle("Delete Time Table")
                          .setMessage("Are you sure you want to Delete this Time Table?")
                          .setPositiveButton(android.R.string.yes, new DialogInterface.OnClickListener() {
                              public void onClick(DialogInterface dialog, int which) {

                                  cardId = (int)v.getTag();

                                  Log.d("cardId", String.valueOf(cardId));

                                  t = tableList.get(cardId);
                                  id = t.getId();

                                  t = db.getTable(id);
                                  db.deleteTable(t);

                                  Intent intent = new Intent(timeTableList,TimeTableList.class);
                                  timeTableList.finish();
                                  timeTableList.startActivity(intent);

                              }

                          })


                          .setNegativeButton(android.R.string.no, new DialogInterface.OnClickListener() {
                              public void onClick(DialogInterface dialog, int which) {
                                  // do nothing
                              }
                          })

                          .setIcon(R.drawable.ic_warning_black_36dp)
                          .show();
                  return true;
              }

          });


          cv.setOnClickListener(new View.OnClickListener() {
              @Override
              public void onClick(final View v) {

                  cardId = (int)v.getTag();

                  Log.d("cardId", String.valueOf(cardId));

                  t = tableList.get(cardId);
                  id = t.getId();

                  Log.d("Id",String.valueOf(id));

                  editMode = true;
                  Intent i = new Intent(timeTableList, NewTimeTable.class);
                  i.putExtra("editMode", editMode);
                  i.putExtra("tableId", id);
                  timeTableList.startActivity(i);
              }
          });


          cardId = (int) cv.getTag();

          Log.d("cardId", String.valueOf(cardId));

          t = tableList.get(cardId);
          id = t.getId();

          if(status == 1)
          {
              aSwitch.setChecked(true);
          }
          else
          {
              aSwitch.setChecked(false);
          }


          aSwitch.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
              @Override
              public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {



                  if (isChecked) {

                      status = 1;

                      t = db.getTable(id);
                      t.setStatus(status);
                      db.updateStatus(t);

                      Log.d("status", String.valueOf(status));

                      final List<TimeTable> events = db.getAllTables();
                      for (TimeTable cn : events) {
                          String log = "Id: " + cn.getId() + " ,Title: " + cn.getTitle() +
                                  "Status: " + cn.getStatus() + ",color: " + cn.getTableColor();
                          Log.d("Data ", log);
                      }

                  } else {

                      status = 0;

                      t = db.getTable(id);
                      t.setStatus(status);
                      db.updateStatus(t);
                      final List<TimeTable> events = db.getAllTables();
                      for (TimeTable cn : events) {
                          String log = "Id: " + cn.getId() + " ,Title: " + cn.getTitle() +
                                  "Status: " + cn.getStatus() + ",color: " + cn.getTableColor();
                          Log.d("Data ", log);
                      }
                      Log.d("status", String.valueOf(status));
                  }

              }
          });

      }
  }

    public void updateAdapaterList(List<TimeTable> newTimeTableList) {
        //Replace the current list with new list
        this.tableList = newTimeTableList;
        //notify the adapter that the data set has changed
        notifyDataSetChanged();
    }
}

Thank you.

Sid
  • 2,792
  • 9
  • 55
  • 111

2 Answers2

1

You should use IDs nor tags nor any sort of identifier in your view holder, because your view holders are reused in the recycler view. I believe that is what is causing you trouble.

You should use the onBindViewHolder for assigning and linking the data of each view holder with it.

In order to assign listeners and IDs inside that method, you should do something like the following:

public void onBindViewHolder(TableViewHolder tableViewHolder, int i) {
    final TimeTable ci = tableList.get(i);

    //...

    tableViewHolder.setOnSomethingListener() {
    // You can use the ci reference here because you declared it as final
    // When this view is reused and references another position, the listener will be updated on the onBindViewHolder, to reference the new position that it will be being associated with
    }

}

Also, on a sidenote, all your static variables from this class should probably not be static, because if you happen to have more instances of your adapter in other views, you eventually don't want them to interfere with each other.

Luis Miguel Serrano
  • 5,029
  • 2
  • 41
  • 41
1

You should assign things to UI fields referenced in ViewHolder in Adapter's onBindMethod not in ViewHolder.

Example out from your code:

public class TableListAdapter extends RecyclerView.Adapter<TableListAdapter.TableViewHolder> {
  private Context context;

  public TableListAdapter(Context context) {
      this.context = context;
  }
  @Override
  public int getItemCount() {
        return tableList.size();
  }

  @Override
  public void onBindViewHolder(TableViewHolder tableViewHolder, int i) {

    /* update referenced UI fields in view holder */

    tableViewHolder.cv.setOnClickListener(new View.OnClickListener() {

          @Override
          public void onClick(final View v) {

              cardId = (int)v.getTag();

              Log.d("cardId", String.valueOf(cardId));

              t = tableList.get(cardId);
              id = t.getId();

              Log.d("Id",String.valueOf(id));

              editMode = true;
              Intent i = new Intent(timeTableList, NewTimeTable.class);
              i.putExtra("editMode", editMode);
              i.putExtra("tableId", id);
              timeTableList.startActivity(i);
          }
      });    

      tableViewHolder.cv.setOnLongClickListener(new View.OnLongClickListener() {

            @Override
            public boolean onLongClick(final View v) {
                // TODO Auto-generated method stub

                final AlertDialog.Builder builder = new AlertDialog.Builder(timeTableList);

                builder.setTitle("Delete Time Table")
                        .setMessage("Are you sure you want to Delete this Time Table?")
                        .setPositiveButton(android.R.string.yes, new DialogInterface.OnClickListener() {
                            public void onClick(DialogInterface dialog, int which) {

                                cardId = (int)v.getTag();

                                Log.d("cardId", String.valueOf(cardId));

                                t = tableList.get(cardId);
                                id = t.getId();

                                t = db.getTable(id);
                                db.deleteTable(t);

                                Intent intent = new Intent(timeTableList,TimeTableList.class);
                                timeTableList.finish();
                                timeTableList.startActivity(intent);

                            }

                        })


                        .setNegativeButton(android.R.string.no, new DialogInterface.OnClickListener() {
                            public void onClick(DialogInterface dialog, int which) {
                                // do nothing
                            }
                        })

                        .setIcon(R.drawable.ic_warning_black_36dp)
                        .show();
                return true;
            }

        });
  }

 @Override
 public TableViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {

    /* Inflate view and pass it to view holder */
    View  itemView = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.table_card, viewGroup, false);

    return new TableViewHolder(itemView);
 }

public static class TableViewHolder extends RecyclerView.ViewHolder {

    protected TextView tableTitle;
    protected CardView cv;
    protected SwitchCompat aSwitch;
    protected Button color;


    public TableViewHolder(View v) {
        super(v);

        cv = (CardView) v.findViewById(R.id.card_view);   // Reference your layout fields.

    }    
}

}

Omkar
  • 1,493
  • 3
  • 17
  • 36