Button inside RecyclerView

I have a problem with my android app. I have a RecyclerView and a click handler for it. When you click on a list item, one of the class fields is displayed on the screen. Also inside there is a button, by clicking on which another class field should be displayed. But the program throws a NullPointerException. I understand why this is happening, but I cannot understand how to modify my code, please help.

here is my Adapeter

package com.skorbr.stock_yandextest;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;

import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;

import java.util.List;

public class TickerAdapter extends RecyclerView.Adapter<TickerAdapter.TickerViewHolder> {

    private List<Ticker> tickers;
    private Context context;
    // listener
    private final Listener onTickerClickListener;

    // constructor
    public TickerAdapter(List<Ticker> tickers, Listener onTickerClickListener) {
        this.tickers = tickers;
        this.onTickerClickListener = onTickerClickListener;
    }

    @NonNull
    @Override
    public TickerViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        context = parent.getContext();
        View view = LayoutInflater.from(context).inflate(R.layout.recycler_stock_item, parent, false);
        // click on RecyclerView
        view.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                onTickerClickListener.onTickerClick((Ticker) v.getTag());
            }
        });
        // click on button
        view.findViewById(R.id.button_favourite).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                onTickerClickListener.onFavouriteClick((Ticker) v.getTag());
            }
        });
        return new TickerViewHolder(view);
    }

    @Override
    public void onBindViewHolder(@NonNull TickerViewHolder holder, int position) {
        Ticker ticker = tickers.get(position);
        holder.bind(ticker);
        holder.itemView.setTag(ticker);
    }

    @Override
    public int getItemCount() {
        return tickers.size();
    }

    class TickerViewHolder extends RecyclerView.ViewHolder {

        private TextView ticker;
        private TextView tickerFull;
        private TextView price;
        private TextView priceChange;
        private ImageView tickerLogo;
        private Button favouriteButton;

        public TickerViewHolder(@NonNull final View itemView) {
            super(itemView);
            ticker = itemView.findViewById(R.id.ticker);
            tickerFull = itemView.findViewById(R.id.ticker_full);
            price = itemView.findViewById(R.id.price);
            priceChange = itemView.findViewById(R.id.price_change);
            tickerLogo = itemView.findViewById(R.id.ticker_image);
            favouriteButton = itemView.findViewById(R.id.button_favourite);
        }

        // заполнение элемента RecyclerView данными
        void bind(Ticker ticker) {
            double priceNow = ticker.getPrice();
            double priceDayAgo = ticker.getPriceDayAgo();
            String sign = "";

            this.ticker.setText(ticker.getTicker());
            this.tickerFull.setText(ticker.getTickerFull());
            this.price.setText("$" + priceNow);
            // check price
            if (priceNow < priceDayAgo) {
                sign = "-";
                this.priceChange.setTextColor(context.getResources().getColor(R.color.colorRedDm));
            } else if (priceNow > priceDayAgo) {
                sign = "+";
                this.priceChange.setTextColor(context.getResources().getColor(R.color.colorGreenDm));
            }
            // check favourites
            if (ticker.isFavourite()) {
                this.favouriteButton.setBackground(context.getDrawable(R.drawable.ic_favourite_on));
            } else {
                this.favouriteButton.setBackground(context.getDrawable(R.drawable.ic_favourite_off));
            }
            this.priceChange.setText(String.format("%s$%.2f (%.2f%%)", sign, Math.abs(priceNow-priceDayAgo), Math.abs(priceNow/priceDayAgo*100-100)));
            this.tickerLogo.setImageResource(ticker.getTickerLogo());
        }
    }

    interface Listener {
        void onTickerClick(Ticker ticker);
        void onFavouriteClick(Ticker ticker);
    }
}

Here is my Main Activity

package com.skorbr.stock_yandextest;

import android.app.Activity;
import android.os.Bundle;
import android.widget.Toast;

import androidx.annotation.Nullable;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;

import java.util.ArrayList;
import java.util.List;

public class ActivityMain extends Activity {

    private RecyclerView tickerList;
    private TickerAdapter tickerAdapter;
    private List<Ticker> tickerListList;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        tickerListList = tickerList();

        tickerList = findViewById(R.id.tickers_list);
        LinearLayoutManager layoutManager = new LinearLayoutManager(this);
        tickerList.setLayoutManager(layoutManager);

        tickerAdapter = new TickerAdapter(tickerListList, new TickerAdapter.Listener() {
            @Override
            public void onTickerClick(Ticker ticker) {
                Toast.makeText(ActivityMain.this, ticker.getTickerFull(), Toast.LENGTH_SHORT);
            }

            @Override
            public void onFavouriteClick(Ticker ticker) {
                Toast.makeText(ActivityMain.this, ticker.getTicker(), Toast.LENGTH_SHORT);
            }
        });
        tickerList.setAdapter(tickerAdapter);

    }

    private List<Ticker> tickerList() {
        List<Ticker> tickers = new ArrayList<>();
        tickers.add(new Ticker("APPL", "Apple Inc.", 138.54, 150.22, R.drawable.apple_logo, false));
        tickers.add(new Ticker("TSLA", "Tesla Motors", 904.37, 753.92, R.drawable.tesla_logo, true));
        tickers.add(new Ticker("GOOGL", "Alphabel Class A", 1845.90, 1845.90, R.drawable.google_logo, false));
        return tickers;
    }
}

Here is my class for data

package com.skorbr.stock_yandextest;
public class Ticker {

    private String ticker;
    private String tickerFull;
    private double price;
    private double priceDayAgo;
    private int tickerLogo;
    private boolean isFavourite;

    public Ticker(String ticker, String tickerFull, double price, double priceDayAgo, int tickerLogo, boolean isFavourite) {
        this.ticker = ticker;
        this.tickerFull = tickerFull;
        this.price = price;
        this.priceDayAgo = priceDayAgo;
        this.tickerLogo = tickerLogo;
        this.isFavourite = isFavourite;
    }

    public String getTicker() {
        return ticker;
    }

    public String getTickerFull() {
        return tickerFull;
    }

    public double getPrice() {
        return price;
    }

    public double getPriceDayAgo() {
        return priceDayAgo;
    }

    public int getTickerLogo() {
        return tickerLogo;
    }

    public boolean isFavourite() {
        return isFavourite;
    }

    public void setFavourite(boolean favourite) {
        isFavourite = favourite;
    }
}

Answer

@Override
public void onBindViewHolder(@NonNull TickerViewHolder holder, int position) {
  Ticker ticker = tickers.get(position);
  holder.bind(ticker);
  holder.itemView.setTag(ticker);
  // add this line
  holder.favouriteButton.setTag(ticker);
}

Or you can modify the onCreateViewHolder()

view.findViewById(R.id.button_favourite).setOnClickListener(new View.OnClickListener() {
  @Override
  public void onClick(View v) {
    // instead of  
    onTickerClickListener.onFavouriteClick((Ticker) v.getTag());
    // use 
    onTickerClickListener.onFavouriteClick((Ticker) view.getTag());
  }
});

Leave a Reply

Your email address will not be published. Required fields are marked *