Home > Mobile >  Why do I get a null object reference error when trying to make a button visible after long pressing
Why do I get a null object reference error when trying to make a button visible after long pressing

Time:10-12

I'm trying to make a button visible when a user long clicks on a row in the recycler view. However I'm getting a null object reference error and not sure why. The Toast works so I know that the long press is working on each row.

Edit - Crash Log:

E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.example.it_stock, PID: 13959
    java.lang.NullPointerException: Attempt to invoke virtual method 'void android.view.View.setVisibility(int)' on a null object reference
        at com.example.it_stock.StockAdapter$ViewHolder.onLongClick(StockAdapter.java:85)
        at android.view.View.performLongClickInternal(View.java:5714)
        at android.view.View.performLongClick(View.java:5672)
        at android.view.View.performLongClick(View.java:5690)
        at android.view.View$CheckForLongPress.run(View.java:22402)
        at android.os.Handler.handleCallback(Handler.java:751)
        at android.os.Handler.dispatchMessage(Handler.java:95)
        at android.os.Looper.loop(Looper.java:154)
        at android.app.ActivityThread.main(ActivityThread.java:6121)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:889)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:779)

Main Activity:

public class MainActivity extends AppCompatActivity {

    private DBHandler db;
    Button btnAddItem;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        RecyclerView stockView = findViewById(R.id.rvStock);
        LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this);
        stockView.setLayoutManager(linearLayoutManager);
        stockView.setHasFixedSize(true);
        db = new DBHandler(this);
        ArrayList<Stock> allStock = db.getAllStock();

        if (allStock.size() > 0) {
            stockView.setVisibility(View.VISIBLE);
            StockAdapter stockAdapter = new StockAdapter(this, allStock);
            stockView.setAdapter(stockAdapter);
        }
        else {
            stockView.setVisibility(View.GONE);
            Toast.makeText(this, "No Items!", Toast.LENGTH_LONG).show();
        }

        btnAddItem = findViewById(R.id.btnAdd);
        btnAddItem.setOnClickListener(v -> {
            addNewItem();
        });
    }

    protected void addNewItem() {
        Intent i = new Intent(MainActivity.this, AddNewItem.class);
        startActivity(i);
    }
}

Adapter:

public class StockAdapter extends RecyclerView.Adapter<StockAdapter.ViewHolder> {

    private Context context;
    private ArrayList<Stock> listStock;
    private ArrayList<Stock> mArrayList;
    private DBHandler db;
    private MainActivity mainActivity;

    StockAdapter(Context context, ArrayList<Stock> listStock) {
        this.context = context;
        this.listStock = listStock;
        this.mArrayList = listStock;
        db = new DBHandler(context);
        mainActivity = new MainActivity();
    }

    @NonNull
    @Override
    public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        LayoutInflater inflater = LayoutInflater.from(parent.getContext());
        View stockView = inflater.inflate(R.layout.stock_row, parent, false);
        return new ViewHolder(stockView);
    }

    @Override
    public void onBindViewHolder(ViewHolder holder, int position) {
        final Stock stock = listStock.get(position);
        holder.tvItem.setText(stock.getItem());
        holder.tvCondition.setText(stock.getCondition());
        holder.tvQuantity.setText(String.valueOf(stock.getQuantity()));
        holder.tvLocation.setText(stock.getLocation());
        holder.tvCategory.setText(stock.getCategory());
    }

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

    class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener, View.OnLongClickListener {
        final TextView tvItem;
        final TextView tvCondition;
        final TextView tvQuantity;
        final TextView tvLocation;
        final TextView tvCategory;
        Button btnRemove;
        View stockView;

        ViewHolder(View stockView) {
            super(stockView);
            this.stockView = stockView;
            stockView.setOnClickListener(this);
            stockView.setOnLongClickListener(this);
            tvItem = stockView.findViewById(R.id.tvItem);
            tvCondition = stockView.findViewById(R.id.tvCondition);
            tvQuantity = stockView.findViewById(R.id.tvQuantity);
            tvLocation = stockView.findViewById(R.id.tvLocation);
            tvCategory = stockView.findViewById(R.id.tvCategory);
            btnRemove = stockView.findViewById(R.id.btnRemove);
        }

        @Override
        public void onClick(View stockView) {

        }

        @Override
        public boolean onLongClick(View stockView) {
            btnRemove.setVisibility(View.VISIBLE);
            Toast.makeText(context, "long pressed", Toast.LENGTH_SHORT).show();
            return false;
        }
    }
}

The button should appear just below the recycler view in activity_main and I have set this up in my xml file and set the button to 'invisible'. Please can someone explain why I'm getting the error and how to fix it?

CodePudding user response:

if btnRemove is null it means stockView.findViewById(R.id.btnRemove) returns null so it means there is no View with id btnRemove in R.layout.stock_row

check if you have this line in R.layout.stock_row :

android:id="@ id/btnRemove"

CodePudding user response:

Modify your code like this, you have initialize listeners before the button.

ViewHolder(View stockView) {
            super(stockView);
            this.stockView = stockView;
            tvItem = stockView.findViewById(R.id.tvItem);
            tvCondition = stockView.findViewById(R.id.tvCondition);
            tvQuantity = stockView.findViewById(R.id.tvQuantity);
            tvLocation = stockView.findViewById(R.id.tvLocation);
            tvCategory = stockView.findViewById(R.id.tvCategory);
            btnRemove = stockView.findViewById(R.id.btnRemove);
            stockView.setOnClickListener(this);
            stockView.setOnLongClickListener(this);

        } 
  • Related