I am trying to add firebase Realtime database into my cart fragment and I want that when someone clicks on the checkout button they should be redirected to checkout activity and the products he ordered should go to the firebase database there is no error but when I run the app .The app closes down and in log cat there is this error.
LogCat
2021-04-07 05:14:29.398 8294-8294/com.example.naashtae E/xample.naashta: [qarth_debug:] get PatchStore::createDisableExceptionQarthFile method fail.
--------- beginning of crash
2021-04-07 05:14:29.400 8294-8294/com.example.naashtae E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.naashtae, PID: 8294
java.lang.NullPointerException: Attempt to invoke virtual method 'void android.widget.Spinner.setSelection(int, boolean)' on a null object reference
at com.example.shoppingcart.models.CartItem.getSelectedSpinnerValue(CartItem.java:54)
at com.example.shoppingcart.views.CartFragment.confirm(CartFragment.java:138)
at com.example.shoppingcart.views.CartFragment$3.onClick(CartFragment.java:116)
at android.view.View.performClick(View.java:6659)
at com.google.android.material.button.MaterialButton.performClick(MaterialButton.java:1119)
at android.view.View.performClickInternal(View.java:6631)
at android.view.View.access$3100(View.java:790)
at android.view.View$PerformClick.run(View.java:26187)
at android.os.Handler.handleCallback(Handler.java:907)
at android.os.Handler.dispatchMessage(Handler.java:105)
at android.os.Looper.loop(Looper.java:216)
at android.app.ActivityThread.main(ActivityThread.java:7625)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:524)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:987)
CartFragment.java
package com.example.shoppingcart.views;
import android.content.Intent; import android.os.Bundle;
import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.databinding.BindingAdapter; import androidx.fragment.app.Fragment; import androidx.lifecycle.Observer; import androidx.lifecycle.ViewModelProvider; import androidx.navigation.NavController; import androidx.navigation.Navigation; import androidx.recyclerview.widget.DividerItemDecoration;
import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.Button; import android.widget.Spinner; import android.widget.TextView;
import com.example.shoppingcart.R; import com.example.shoppingcart.adapters.CartListAdapter; import com.example.shoppingcart.cartholder; import com.example.shoppingcart.databinding.FragmentCartBinding; import com.example.shoppingcart.models.CartItem; import com.example.shoppingcart.viewmodels.ShopViewModel; import com.google.firebase.database.DatabaseReference; import com.google.firebase.database.FirebaseDatabase; import com.google.firebase.firestore.FirebaseFirestore;
import java.text.SimpleDateFormat; import java.util.Calendar; import java.util.List; import java.util.UUID;
public class CartFragment extends Fragment implements CartListAdapter.CartInterface {
private static final String TAG = "CartFragment";
FirebaseFirestore firebaseFirestore;
public TextView productprice;
public Spinner productquantity;
Spinner spinner;
int quantity;
ShopViewModel shopViewModel;
FragmentCartBinding fragmentCartBinding;
NavController navController;
Button button;
private void finishActivity() {
if (getActivity() != null) {
getActivity().finish();
}
}
public CartFragment() {
// Required empty public constructor
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
fragmentCartBinding = FragmentCartBinding.inflate(inflater, container, false);
firebaseFirestore = FirebaseFirestore.getInstance();
return fragmentCartBinding.getRoot();
}
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
navController = Navigation.findNavController(view);
final CartListAdapter cartListAdapter = new CartListAdapter(this);
fragmentCartBinding.cartRecyclerView.setAdapter(cartListAdapter);
fragmentCartBinding.cartRecyclerView.addItemDecoration(new DividerItemDecoration(requireContext(), DividerItemDecoration.VERTICAL));
shopViewModel = new ViewModelProvider(requireActivity()).get(ShopViewModel.class);
shopViewModel.getCart().observe(getViewLifecycleOwner(), new Observer<List<CartItem>>() {
@Override
public void onChanged(List<CartItem> cartItems) {
cartListAdapter.submitList(cartItems);
fragmentCartBinding.placeOrderButton.setEnabled(cartItems.size() > 0);
}
});
shopViewModel.getTotalPrice().observe(getViewLifecycleOwner(), new Observer<Double>() {
@Override
public void onChanged(Double aDouble) {
fragmentCartBinding.orderTotalTextView.setText("Total: PKR " + aDouble.toString());
String price=aDouble.toString().trim();
}
});
button = (Button) getView().findViewById(R.id.placeOrderButton);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
confirm();
}
});
}
public void confirm() {
productprice = getView().findViewById(R.id.orderTotalTextView);
final String saveCurrentDate, saveCurrentTime;
Calendar calForDate = Calendar.getInstance();
SimpleDateFormat currentDate = new SimpleDateFormat("MMM dd, yyyy");
saveCurrentDate = currentDate.format(calForDate.getTime());
SimpleDateFormat currentTime = new SimpleDateFormat("HH:mm:ss a");
saveCurrentTime = currentTime.format(calForDate.getTime());
String productPrice = productprice.toString().trim();
String productq= CartItem.getSelectedSpinnerValue(spinner,quantity).trim();
UUID uuid = UUID.randomUUID();
String randomUUIDString = uuid.toString().trim();
cartholder op = new cartholder(productPrice,productq, saveCurrentDate, saveCurrentTime);
FirebaseDatabase dab = FirebaseDatabase.getInstance();
DatabaseReference note = dab.getReference(randomUUIDString);
note.child("Products").setValue(op);
Intent intent = new Intent(CartFragment.this.getActivity(), CheckoutActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
startActivity(intent);
finishActivity();
}
@Override
public void deleteItem(CartItem cartItem) {
shopViewModel.removeItemFromCart(cartItem);
}
@Override
public void changeQuantity(CartItem cartItem, int quantity) {
shopViewModel.changeQuantity(cartItem, quantity);
}
}
fragment_cart.xml
<?xml version="1.0" encoding="utf-8"?>
<ScrollView 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">
<LinearLayout
android:orientation="vertical"
tools:context=".views.CartFragment"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/cartRecyclerView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
tools:listitem="@layout/cart_row"
tools:itemCount="2"
/>
<Space
android:layout_width="match_parent"
android:layout_height="16dp" />
<TextView
android:id="@+id/orderTotalTextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="end"
android:layout_margin="8dp"
android:text="Total: PKR 26"
android:textAppearance="@style/TextAppearance.MaterialComponents.Headline6" />
<Button
android:id="@+id/placeOrderButton"
style="@style/Widget.MaterialComponents.Button.UnelevatedButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="end"
android:layout_margin="8dp"
android:text="Proceed To Checkout"
android:textAppearance="@style/TextAppearance.MaterialComponents.Caption" />
</LinearLayout>
</ScrollView>
CartItem.java
package com.example.shoppingcart.models;
import android.widget.Spinner;
import androidx.annotation.NonNull;
import androidx.databinding.BindingAdapter;
import androidx.recyclerview.widget.DiffUtil;
public class CartItem {
private Product product;
private int quantity;
public CartItem(Product product, int quantity) {
this.product = product;
this.quantity = quantity;
}
public Product getProduct() {
return product;
}
public void setProduct(Product product) {
this.product = product;
}
public int getQuantity() {
return quantity;
}
public void setQuantity(int quantity) {
this.quantity = quantity;
}
@Override
public String toString() {
return "CartItem{" +
"product=" + product +
", quantity=" + quantity +
'}';
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
CartItem cartItem = (CartItem) o;
return getQuantity() == cartItem.getQuantity() &&
getProduct().equals(cartItem.getProduct());
}
@BindingAdapter("android:setVal")
public static String getSelectedSpinnerValue(Spinner spinner, int quantity) {
spinner.setSelection(quantity - 1, true);
return spinner.getSelectedItem().toString();
}
public static DiffUtil.ItemCallback<CartItem> itemCallback = new DiffUtil.ItemCallback<CartItem>() {
@Override
public boolean areItemsTheSame(@NonNull CartItem oldItem, @NonNull CartItem newItem) {
return oldItem.getQuantity() == newItem.getQuantity();
}
@Override
public boolean areContentsTheSame(@NonNull CartItem oldItem, @NonNull CartItem newItem) {
return oldItem.equals(newItem);
}
};
}
carthoder.java
package com.example.shoppingcart;
public class cartholder {
String productPrice,productq,Time,Date;
public cartholder( String productPrice,String productq, String time, String date) {
this.productPrice = productPrice;
this.productq=productq;
Time = time;
Date = date;
}
public String getProductPrice() {
return productPrice;
}
public void setProductPrice(String productPrice) {
this.productPrice = productPrice;
}
public String getProductq() {
return productq;
}
public void setProductq(String productq) {
this.productq = productq;
}
public String getTime() {
return Time;
}
public void setTime(String time) {
Time = time;
}
public String getDate() {
return Date;
}
public void setDate(String date) {
Date = date;
}
}
CartRepo.java
package com.example.shoppingcart.repositories;
import androidx.lifecycle.LiveData;
import androidx.lifecycle.MutableLiveData;
import com.example.shoppingcart.models.CartItem;
import com.example.shoppingcart.models.Product;
import java.util.ArrayList;
import java.util.List;
public class CartRepo {
private MutableLiveData<List<CartItem>> mutableCart = new MutableLiveData<>();
private MutableLiveData<Double> mutableTotalPrice = new MutableLiveData<>();
public LiveData<List<CartItem>> getCart() {
if (mutableCart.getValue() == null) {
initCart();
}
return mutableCart;
}
public void initCart() {
mutableCart.setValue(new ArrayList<CartItem>());
calculateCartTotal();
}
public boolean addItemToCart(Product product) {
if (mutableCart.getValue() == null) {
initCart();
}
List<CartItem> cartItemList = new ArrayList<>(mutableCart.getValue());
for (CartItem cartItem: cartItemList) {
if (cartItem.getProduct().getId().equals(product.getId())) {
if (cartItem.getQuantity() == 5) {
return false;
}
int index = cartItemList.indexOf(cartItem);
cartItem.setQuantity(cartItem.getQuantity() + 1);
cartItemList.set(index, cartItem);
mutableCart.setValue(cartItemList);
calculateCartTotal();
return true;
}
}
CartItem cartItem = new CartItem(product, 1);
cartItemList.add(cartItem);
mutableCart.setValue(cartItemList);
calculateCartTotal();
return true;
}
public void removeItemFromCart(CartItem cartItem) {
if (mutableCart.getValue() == null) {
return;
}
List<CartItem> cartItemList = new ArrayList<>(mutableCart.getValue());
cartItemList.remove(cartItem);
mutableCart.setValue(cartItemList);
calculateCartTotal();
}
public void changeQuantity(CartItem cartItem, int quantity) {
if (mutableCart.getValue() == null) return;
List<CartItem> cartItemList = new ArrayList<>(mutableCart.getValue());
CartItem updatedItem = new CartItem(cartItem.getProduct(), quantity);
cartItemList.set(cartItemList.indexOf(cartItem), updatedItem);
mutableCart.setValue(cartItemList);
calculateCartTotal();
}
private void calculateCartTotal() {
if (mutableCart.getValue() == null) return;
double total = 0.0;
List<CartItem> cartItemList = mutableCart.getValue();
for (CartItem cartItem: cartItemList) {
total += cartItem.getProduct().getPrice() * cartItem.getQuantity();
}
mutableTotalPrice.setValue(total);
}
public LiveData<Double> getTotalPrice() {
if (mutableTotalPrice.getValue() == null) {
mutableTotalPrice.setValue(0.0);
}
return mutableTotalPrice;
}
}
CartListAdapter.java
package com.example.shoppingcart.adapters;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.DiffUtil;
import androidx.recyclerview.widget.ListAdapter;
import androidx.recyclerview.widget.RecyclerView;
import com.example.shoppingcart.databinding.CartRowBinding;
import com.example.shoppingcart.models.CartItem;
public class CartListAdapter extends ListAdapter<CartItem, CartListAdapter.CartVH> {
private CartInterface cartInterface;
public CartListAdapter(CartInterface cartInterface) {
super(CartItem.itemCallback);
this.cartInterface = cartInterface;
}
@NonNull
@Override
public CartVH onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
LayoutInflater layoutInflater = LayoutInflater.from(parent.getContext());
CartRowBinding cartRowBinding = CartRowBinding.inflate(layoutInflater, parent, false);
return new CartVH(cartRowBinding);
}
@Override
public void onBindViewHolder(@NonNull CartVH holder, int position) {
holder.cartRowBinding.setCartItem(getItem(position));
holder.cartRowBinding.executePendingBindings();
}
class CartVH extends RecyclerView.ViewHolder {
CartRowBinding cartRowBinding;
public CartVH(@NonNull CartRowBinding cartRowBinding) {
super(cartRowBinding.getRoot());
this.cartRowBinding = cartRowBinding;
cartRowBinding.deleteProductButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
cartInterface.deleteItem(getItem(getAdapterPosition()));
}
});
cartRowBinding.quantitySpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
int quantity = position + 1;
if (quantity == getItem(getAdapterPosition()).getQuantity()) {
return;
}
cartInterface.changeQuantity(getItem(getAdapterPosition()), quantity);
}
@Override
public void onNothingSelected(AdapterView<?> parent) {
}
});
}
}
public interface CartInterface {
void deleteItem(CartItem cartItem);
void changeQuantity(CartItem cartItem, int quantity);
}
}
The logcat is telling you you have a null object reference
in CartItem.java:54
This method
public static String getSelectedSpinnerValue(Spinner spinner, int quantity) {
spinner.setSelection(quantity - 1, true);
return spinner.getSelectedItem().toString();
}
is getting a null spinner when you called it from CartFragment.confirm(CartFragment.java:138)
String productq= CartItem.getSelectedSpinnerValue(spinner,quantity).trim();
that is because spinner
is null, you never used spinner = findViewById(R.id.spinner);
or anything like that.