Reputation: 49
I'm trying to complete the functionality of shopping badge card. But, I face a problem When my shopping cart has many items, my app and the shopping badge works perfectly. Also, when I have 1 item in my shopping cart my app and the shopping badge works perfectly. But when i remove all items for my shopping cart and badge equals with 0, the next move will cause an error in the application. Αnd more specifically, it causes problem :
java.lang.NullPointerException: Attempt to read from field
'android.widget.Button com.example.myapp.CartActivity.btnPlace' on a
null object reference
at com.example.myapp.Adapter.CartAdapter.getItemCount(CartAdapter.java:120)
at com.example.myapp.FragmentDetails.CoffeeDetails.onOptionsItemSelected(CoffeeDetails.java:174)
Below I quote my code : My code of CartAdapter is:
public class CartAdapter extends RecyclerView.Adapter<CartAdapter.CartViewHolder> {
private List<CoffeeOrder> listData = new ArrayList<>();
CartActivity cart;
private OnCartListener mOnCartListener;
public CartAdapter(CartActivity cart, List<CoffeeOrder> listData, OnCartListener onCartListener){
this.listData = listData;
this.cart = cart;
this.mOnCartListener = onCartListener;
}
@NonNull
@Override
public CartViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View v = LayoutInflater.from(cart).inflate(R.layout.cart_item , parent, false);
return new CartViewHolder(v,mOnCartListener);
}
@Override
public void onBindViewHolder(@NonNull CartViewHolder holder, int position) {
CoffeeOrder order = listData.get(position);
holder.txt_cart_name.setText( order.getProductName());
holder.txt_price.setText(order.getPrice() + " \u20ac");
//change total price if quantity change from elegant number
holder.img_cart_count.setNumber(listData.get(position).getQuantity());
holder.img_cart_count.setOnValueChangeListener(new ElegantNumberButton.OnValueChangeListener() {
@Override
public void onValueChange(ElegantNumberButton view, int oldValue, int newValue) {
CoffeeOrder coffeeOrder = listData.get(position);
coffeeOrder.setQuantity(String.valueOf(newValue));
new Database(cart).updateCart(coffeeOrder);
//Update total price
//Calculate total price
Double double_total;
double_total = 0.00;
List <CoffeeOrder> coffeeOrders = new Database(cart).getCarts();
for(CoffeeOrder item:coffeeOrders) {
double_total += (Double.parseDouble(order.getPrice())) * (Double.parseDouble(item.getQuantity()));
}
String total = String.format("%.2f", double_total);
cart.txtTotalPrice.setText(total + " \u20ac");
}
});
//remove item from shopping cart
holder.itemDeleteBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
CoffeeOrder coffeeOrder = listData.get(holder.getAdapterPosition());
listData.remove(holder.getAdapterPosition());
notifyItemRemoved(holder.getAdapterPosition());
new Database(cart).removeFromCart(coffeeOrder);
//Update total price
//Calculate total price
Double double_total;
double_total = 0.00;
List <CoffeeOrder> coffeeOrders = new Database(cart).getCarts();
for(CoffeeOrder item:coffeeOrders) {
double_total += (Double.parseDouble(order.getPrice())) * (Double.parseDouble(item.getQuantity()));
}
String total = String.format("%.2f", double_total);
cart.txtTotalPrice.setText(total + " \u20ac");
}
});
}
@Override
public int getItemCount() {
if (listData.size() == 0){
//making it semi-transparent
cart.btnPlace.setAlpha(.5f);
cart.btnPlace.setEnabled(false);
cart.empty_list.setVisibility(LinearLayout.VISIBLE);
}
return listData.size();
}
public static class CartViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
public TextView txt_cart_name,txt_price;
public ElegantNumberButton img_cart_count;
public ImageView itemDeleteBtn;
OnCartListener onCartListener;
public CartViewHolder(View itemView, OnCartListener onCartListener){
super(itemView);
txt_cart_name = itemView.findViewById(R.id.cart_item_name);
txt_price = itemView.findViewById(R.id.cart_item_price);
img_cart_count = itemView.findViewById(R.id.btn_quantity);
itemDeleteBtn = itemView.findViewById(R.id.btn_item_delete);
this.onCartListener = onCartListener;
txt_cart_name.setOnClickListener(this);
}
@Override
public void onClick(View v) {
onCartListener.onCartItemDelete(getAdapterPosition());
}
}
public interface OnCartListener{
void onCartItemDelete(int position);
}
}
My code of Activity is :
public class CoffeeDetails extends AppCompatActivity implements CartAdapter.OnCartListener{
TextView coffee_name,coffee_price;
ImageView coffee_image;
CollapsingToolbarLayout collapsingToolbarLayout;
Toolbar toolbar;
String coffeeName="Coffee Name Not Set";
String coffeePrice="Coffee Price Not Set";
String coffeeImage="Coffee Image Not Set";
Button btn_add_cart;
FirebaseDatabase database;
DatabaseReference coffee;
String coffeeId = "";
int ID;
RadioGroup group_choose_varieties;
RadioGroup group_choose_sugar;
RadioButton rb2;
RadioButton rb3;
TextView text_buondi;
TextView text_decaffeine;
List<CoffeeOrder> listCart = new ArrayList<>();
CartAdapter adapter;
CartActivity cartActivity;
public int cartQuantity=0;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_coffee_details);
toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
database = FirebaseDatabase.getInstance();
coffee = database.getReference("Coffee");
coffee_name = findViewById(R.id.coffee_name);
coffee_price = findViewById(R.id.coffee_price);
coffee_image = findViewById(R.id.img_coffee);
collapsingToolbarLayout = findViewById(R.id.collapsing);
collapsingToolbarLayout.setExpandedTitleTextAppearance(R.style.ExpandedAppbar);
collapsingToolbarLayout.setCollapsedTitleTextAppearance(R.style.CollapsedAppbar);
btn_add_cart = findViewById(R.id.btn_add_cart);
group_choose_varieties = findViewById(R.id.group_choose_varieties);
group_choose_sugar = findViewById(R.id.group_choose_sugar);
text_buondi = findViewById(R.id.text_buondi);
text_decaffeine = findViewById(R.id.text_decaffeine);
rb2 = findViewById(R.id.rb2);
rb3 = findViewById(R.id.rb3);
Bundle extras = getIntent().getExtras();
if(extras != null){
coffeeName = extras.getString("coffeeName");
coffeePrice = extras.getString("coffeePrice");
coffeeImage = extras.getString("coffeeImage");
}
coffee_name.setText(coffeeName);
collapsingToolbarLayout.setTitle(coffeeName);
coffee_price.setText(coffeePrice + " \u20ac");
Picasso.with(getBaseContext()).load(coffeeImage)
.into(coffee_image);
listCart = new Database(this).getCarts();
adapter = new CartAdapter(cartActivity,listCart, this);
int quantity =0;
if (adapter.getItemCount() != 0){
quantity += adapter.getItemCount();
cartQuantity = quantity;
}
btn_add_cart.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
int isSelected1 = group_choose_varieties.getCheckedRadioButtonId();
int isSelected2 = group_choose_sugar.getCheckedRadioButtonId();
if(isSelected1 == -1 && isSelected2 == -1){
Toast.makeText(CoffeeDetails.this, "Πρέπει να επιλέξετε ποικιλία και ζάχαρη για να συνεχίσετε...", Toast.LENGTH_SHORT).show();
return;
}else if(isSelected1 != -1 && isSelected2 == -1){
Toast.makeText(CoffeeDetails.this, "Πρέπει να επιλέξετε ζάχαρη για να συνεχίσετε...", Toast.LENGTH_SHORT).show();
}else if(isSelected1 == -1 && isSelected2 != -1){
Toast.makeText(CoffeeDetails.this, "Πρέπει να επιλέξετε ποικιλία για να συνεχίσετε...", Toast.LENGTH_SHORT).show();
}else {
new Database(getBaseContext()).addToCart(new CoffeeOrder(
ID,
coffeeId,
coffeeName,
"1",
coffeePrice
));
Toast.makeText(getApplication(), "Το προϊόν προστέθηκε στο καλάθι σας!", Toast.LENGTH_SHORT).show();
}
}
});
}
// Add shopping cart icon in toolbar
public boolean onCreateOptionsMenu(Menu menu){
getMenuInflater().inflate(R.menu.menu, menu);
MenuItem menuItem = menu.findItem(R.id.cartFragment);
View actionView = menuItem.getActionView();
TextView cartBadgeTextView = (TextView)actionView.findViewById(R.id.cart_badge_text_view);
cartBadgeTextView.setText(String.valueOf(cartQuantity));
actionView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
onOptionsItemSelected(menuItem);
}
});
return true;
}
public boolean onOptionsItemSelected(MenuItem item){
int id = item.getItemId();
if(id == R.id.cartFragment){
Intent intent = new Intent(CoffeeDetails.this, CartActivity.class);
startActivity(intent);
return true;
}
return super.onOptionsItemSelected(item);
}
@Override
public void onCartItemDelete(int position) {
}
}
My code of Cart Activity is:
public class CartActivity extends AppCompatActivity implements CartAdapter.OnCartListener{
Toolbar toolbar;
RecyclerView recyclerView;
RecyclerView.LayoutManager layoutManager;
public TextView txtTotalPrice;
public Button btnPlace;
List<CoffeeOrder> listCart = new ArrayList<>();
CartAdapter adapter;
public LinearLayout empty_list;
FirebaseDatabase database;
DatabaseReference requests;
private FirebaseUser user;
private DatabaseReference reference;
private String userID;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_cart);
toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
database = FirebaseDatabase.getInstance();
requests = database.getReference("Requests");
user = FirebaseAuth.getInstance().getCurrentUser();
reference = FirebaseDatabase.getInstance().getReference("Users");
userID = user.getUid();
recyclerView = findViewById(R.id.listCart);
recyclerView.setHasFixedSize(true);
layoutManager = new LinearLayoutManager(this);;
recyclerView.setLayoutManager(layoutManager);
txtTotalPrice = findViewById(R.id.total);
btnPlace = findViewById(R.id.btnPlaceOrder);
listCart = new Database(this).getCarts();
adapter = new CartAdapter(this,listCart, this);
recyclerView.setAdapter(adapter);
empty_list = findViewById(R.id.empty_list);
//Calculate total price
Double double_total;
double_total = 0.00;
for(CoffeeOrder order:listCart) {
double_total += (Double.parseDouble(order.getPrice()))*(Double.parseDouble(order.getQuantity()));
}
String total = String.format("%.2f", double_total);
txtTotalPrice.setText(total + " \u20ac");
// check if cart list is empty. If cart list is empty, then disable button
if (adapter.getItemCount() == 0){
//making it semi-transparent
btnPlace.setAlpha(.5f);
btnPlace.setEnabled(false);
empty_list.setVisibility(LinearLayout.VISIBLE);
}
btnPlace.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
showAlertDialog();
}
});
}
private void showAlertDialog(){
AlertDialog.Builder builder = new AlertDialog.Builder(CartActivity.this);
EditText edtAddress = new EditText(this);
LinearLayout.LayoutParams editTextParams = new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.MATCH_PARENT,
LinearLayout.LayoutParams.MATCH_PARENT);
TextInputLayout textInputLayout = new TextInputLayout(this, null, R.style.Widget_MaterialComponents_TextInputLayout_OutlinedBox);
LinearLayout.LayoutParams textInputLayoutParams = new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.MATCH_PARENT,
LinearLayout.LayoutParams.WRAP_CONTENT);
textInputLayout.setLayoutParams(textInputLayoutParams);
textInputLayout.addView(edtAddress, editTextParams);
textInputLayout.setHint("Address");
edtAddress.setTextSize(15);
editTextParams.setMargins(60,30,60,80);
builder.setCancelable(false);
builder.setView(textInputLayout);
builder.setTitle("Ένα βήμα ακόμα");
builder.setMessage("Συμπλήρωσε τη διεύθυνση σου για την ολοκλήρωση της παραγγελίας σου!");
builder.setPositiveButton("Συνέχεια", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
if (TextUtils.isEmpty(edtAddress.getText().toString())) {
Toast.makeText(CartActivity.this, "Το πεδίο είναι απαραίτητο", Toast.LENGTH_SHORT).show();
}else{
user = FirebaseAuth.getInstance().getCurrentUser();
reference = FirebaseDatabase.getInstance().getReference("Users");
userID = user.getUid();
Request request = new Request(
userID,
edtAddress.getText().toString(),
txtTotalPrice.getText().toString(),
listCart
);
//Submit to Firebase
requests.child(String.valueOf(System.currentTimeMillis()))
.setValue(request);
//Delete Cart
new Database(getBaseContext()).cleanCart();
Toast.makeText(getApplication(),"Σας ευχαριστούμε για την παραγγελία σας!", Toast.LENGTH_SHORT).show();
startActivity(new Intent(CartActivity.this, MainFragment.class));
finish();
}
}
});
builder.setNegativeButton("Ακύρωση", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
}
});
AlertDialog alertDialog = builder.create();
alertDialog.show();
}
@Override
public void onCartItemDelete(int position) {
}
}
My xml code of cart axctivity is:
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".CartActivity">
<com.google.android.material.appbar.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">
<androidx.appcompat.widget.Toolbar
app:title="Το καλάθι σας"
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="@color/black"
app:layout_scrollFlags="scroll|enterAlways"
app:popupTheme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"/>
</com.google.android.material.appbar.AppBarLayout>
<androidx.core.widget.NestedScrollView
android:id="@+id/nestedScrollView"
android:clipToPadding="false"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@drawable/cart_background"
app:layout_behavior="@string/appbar_scrolling_view_behavior">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
>
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/listCart"
android:background="@android:color/transparent"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginBottom="105dp"/>
</LinearLayout>
</androidx.core.widget.NestedScrollView>
<LinearLayout
android:id="@+id/empty_list"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:orientation="vertical"
android:visibility="gone"
tools:visibility="invisible">
<ImageView
android:id="@+id/empty_image"
android:layout_width="100dp"
android:layout_height="100dp"
android:src="@drawable/ic_empty_box" />
<TextView
android:id="@+id/emptyMessage"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Η λίστα σας είναι κενή!"
android:textSize="15sp"
android:alpha="0.7"
android:textColor="@color/black" />
</LinearLayout>
<androidx.cardview.widget.CardView
android:layout_gravity="bottom"
android:layout_marginStart="5dp"
android:layout_marginEnd="5dp"
android:layout_marginBottom="5dp"
android:layout_alignParentBottom="true"
app:cardBackgroundColor="@color/register_background"
android:layout_width="match_parent"
android:layout_height="100dp">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_margin="8dp"
android:gravity="center"
android:orientation="horizontal"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<TextView
android:text="Συνολικό ποσό: "
android:textSize="20sp"
android:textColor="@color/black"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView
android:id="@+id/total"
android:textSize="18sp"
android:textColor="@color/black"
android:textStyle="bold"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
<Button
android:id="@+id/btnPlaceOrder"
android:text="Ολοκλήρωση Παραγγελίας"
android:textColor="@color/black"
android:layout_marginRight="8dp"
android:backgroundTint="@color/yellow"
android:layout_marginLeft="8dp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="40dp"
android:textAllCaps="false"
/>
</RelativeLayout>
</androidx.cardview.widget.CardView>
</androidx.coordinatorlayout.widget.CoordinatorLayout>
Upvotes: 0
Views: 77