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);
}