首页 > 解决方案 > 我该如何解决这个错误?java.lang.NullPointerException:尝试在空对象引用上调用虚拟方法“xxx”

问题描述

不知道发生了什么,我知道我的 SizeModel 对象为空,但我不知道代码的哪一部分有错误。

日志猫

java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.Long com.android.ridefun.Model.SizeModel.getPrice()' on a null object reference
    at com.android.ridefun.ui.fooddetail.FoodDetailFragment.calculateTotalPrice(FoodDetailFragment.java:368)
    at com.android.ridefun.ui.fooddetail.FoodDetailFragment.displayInfo(FoodDetailFragment.java:356)
    at com.android.ridefun.ui.fooddetail.FoodDetailFragment.lambda$onCreateView$3$FoodDetailFragment(FoodDetailFragment.java:197)
    at com.android.ridefun.ui.fooddetail.-$$Lambda$FoodDetailFragment$P7ns469KVlm85g5qkSDfjwtWEhE.onChanged(Unknown Source:4)
    at androidx.lifecycle.LiveData.considerNotify(LiveData.java:133)
    at androidx.lifecycle.LiveData.dispatchingValue(LiveData.java:151)
    at androidx.lifecycle.LiveData.setValue(LiveData.java:309)
    at androidx.lifecycle.MutableLiveData.setValue(MutableLiveData.java:50)
    at com.android.ridefun.ui.fooddetail.FoodDetailViewModel.setFoodModel(FoodDetailViewModel.java:41)
    at com.android.ridefun.ui.fooddetail.FoodDetailFragment$1.lambda$onDataChange$0$FoodDetailFragment$1(FoodDetailFragment.java:299)
    at com.android.ridefun.ui.fooddetail.-$$Lambda$FoodDetailFragment$1$kDzBYjkwuFHevzvZPfWIqjcF4o8.onComplete(Unknown Source:4)

FoodDetailFragment.java

private void displayInfo(FoodModel foodModel) {
    Glide.with(getContext()).load(foodModel.getImage()).into(img_food);
    food_name.setText(new StringBuilder(foodModel.getName()));
    food_description.setText(new StringBuilder(foodModel.getDescription()));
    food_price.setText(new StringBuilder(foodModel.getPrice().toString()));

    if(foodModel.getRatingValue() != null)
        ratingBar.setRating(foodModel.getRatingValue().floatValue());

    ((AppCompatActivity)getActivity())
            .getSupportActionBar()
            .setTitle(Common.selectedFood.getName());

    //Size
    for(SizeModel sizeModel: Common.selectedFood.getSize())
    {
        RadioButton radioButton = new RadioButton(getContext());
        radioButton.setOnCheckedChangeListener((compoundButton, b) -> {
            if(b)
                Common.selectedFood.setUserSelectedSize(sizeModel);
            calculateTotalPrice(); //Update price
        });

        LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(0,
                LinearLayout.LayoutParams.MATCH_PARENT,
                1.0f);
        radioButton.setLayoutParams(params);
        radioButton.setText(sizeModel.getName());
        radioButton.setTag(sizeModel.getPrice());

        rdi_group_size.addView(radioButton);

    }

    if(rdi_group_size.getChildCount() > 0)
    {
        RadioButton radioButton = (RadioButton)rdi_group_size.getChildAt(0);
        radioButton.setChecked(true); //Default first select
    }

    calculateTotalPrice();
}

private void calculateTotalPrice() {
    double totalPrice = Double.parseDouble(Common.selectedFood.getPrice().toString()),displayPrice=0.0;

    //Addon
    if(Common.selectedFood.getUserSelectedAddon() != null && Common.selectedFood.getUserSelectedAddon().size() > 0)
        for(AddonModel addonModel : Common.selectedFood.getUserSelectedAddon())
            totalPrice+=Double.parseDouble(addonModel.getPrice().toString());

    //size
    totalPrice += Double.parseDouble(Common.selectedFood.getUserSelectedSize().getPrice().toString());

    displayPrice = totalPrice * (Integer.parseInt(numberButton.getNumber()));
    displayPrice = Math.round(displayPrice*100.0/100.0);

    food_price.setText(new StringBuilder("").append(Common.formatPrice(displayPrice)).toString());
}

@Override
public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
    //Null
}

@Override
public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
    chip_group_addon.clearCheck();
    chip_group_addon.removeAllViews();

    for(AddonModel addonModel:Common.selectedFood.getAddon())
    {
        if(addonModel.getName().toLowerCase().contains(charSequence.toString().toLowerCase()))
        {
            Chip chip = (Chip)getLayoutInflater().inflate(R.layout.layout_addon_item,null);
            chip.setText(new StringBuilder(addonModel.getName()).append("(+$")
            .append(addonModel.getPrice()).append(")"));
            chip.setOnCheckedChangeListener((compoundButton, b) -> {
                if(b)
                {
                    if (Common.selectedFood.getUserSelectedAddon() == null)
                        Common.selectedFood.setUserSelectedAddon(new ArrayList<>());
                    Common.selectedFood.getUserSelectedAddon().add(addonModel);
                }
            });
            chip_group_addon.addView(chip);
        }
    }
}

@Override
public void afterTextChanged(Editable editable) {

}

FoodViewModel.java

public class FoodDetailFragment extends Fragment implements TextWatcher {

private FoodDetailViewModel foodDetailViewModel;

private Unbinder unbinder;
private android.app.AlertDialog waitingDialog;
private BottomSheetDialog addonBottomSheetDialog;

//View need inflate
ChipGroup chip_group_addon;
EditText edt_search;

@BindView(R.id.img_food)
ImageView img_food;
@BindView(R.id.btnCart)
CounterFab btnCart;
@BindView(R.id.btn_rating)
FloatingActionButton btn_rating;
@BindView(R.id.food_name)
TextView food_name;
@BindView(R.id.food_description)
TextView food_description;
@BindView(R.id.food_price)
TextView food_price;
@BindView(R.id.number_button)
ElegantNumberButton numberButton;
@BindView(R.id.ratingBar)
RatingBar ratingBar;
@BindView(R.id.btnShowComment)
Button btnShowComment;
@BindView(R.id.rdi_group_size)
RadioGroup rdi_group_size;
@BindView(R.id.img_add_addon)
ImageView img_add_on;
@BindView(R.id.chip_group_user_selected_addon)
ChipGroup chip_group_user_selected_addon;

@OnClick(R.id.img_add_addon)
void onAddonClick()
{
    if(Common.selectedFood.getAddon() != null)
    {
        displayAddonList(); //show all addon options
        addonBottomSheetDialog.show();
    }
}

private void displayAddonList() {
    if(Common.selectedFood.getAddon().size() > 0)
    {
        chip_group_addon.clearCheck(); //Clear check all
        chip_group_addon.removeAllViews();

        edt_search.addTextChangedListener(this);

        //Add all view
        for(AddonModel addonModel:Common.selectedFood.getAddon())
        {

                Chip chip = (Chip)getLayoutInflater().inflate(R.layout.layout_addon_item,null);
                chip.setText(new StringBuilder(addonModel.getName()).append("(+$")
                        .append(addonModel.getPrice()).append(")"));
                chip.setOnCheckedChangeListener((compoundButton, b) -> {
                    if(b)
                    {
                        if (Common.selectedFood.getUserSelectedAddon() == null)
                            Common.selectedFood.setUserSelectedAddon(new ArrayList<>());
                        Common.selectedFood.getUserSelectedAddon().add(addonModel);
                    }
                });
                chip_group_addon.addView(chip);

        }

    }
}

@OnClick(R.id.btn_rating)
void onRatingButtonClick()
{
    showDialogRating();
}

@OnClick(R.id.btnShowComment)
void onShowCommentButtonClick() {
    CommentFragment commentFragment = CommentFragment.getInstance();
    commentFragment.show(getActivity().getSupportFragmentManager(),"CommentFragment");
}

private void showDialogRating() {
    androidx.appcompat.app.AlertDialog.Builder builder = new androidx.appcompat.app.AlertDialog.Builder(getContext());
    builder.setTitle("Rating Food");
    builder.setMessage("Please fill information");

    View itemView = LayoutInflater.from(getContext()).inflate(R.layout.layout_rating,null);

    RatingBar ratingBar = (RatingBar)itemView.findViewById(R.id.rating_bar);
    EditText edt_comment = (EditText)itemView.findViewById(R.id.edt_comment);

    builder.setView(itemView);

    builder.setNegativeButton("CANCEL", (dialogInterface, i) -> {
        dialogInterface.dismiss();
    });
    builder.setPositiveButton("OK", (dialogInterface, i) -> {
        CommentModel commentModel = new CommentModel();
        commentModel.setName(Common.currentUser.getName());
        commentModel.setUsername(Common.currentUser.getUsername());
        commentModel.setComment(edt_comment.getText().toString());
        commentModel.setRatingValue(ratingBar.getRating());
        Map<String,Object> serverTimeStamp = new HashMap<>();
        serverTimeStamp.put("timeStamp", ServerValue.TIMESTAMP);
        commentModel.setCommentTimeStamp(serverTimeStamp);

        foodDetailViewModel.setCommentModel(commentModel);

    });

    AlertDialog dialog = builder.create();
    dialog.show();
}


public View onCreateView(@NonNull LayoutInflater inflater,
                         ViewGroup container, Bundle savedInstanceState) {
    foodDetailViewModel =
            new ViewModelProvider(this).get(FoodDetailViewModel.class);
    View root = inflater.inflate(R.layout.fragment_food_detail, container, false);
    unbinder = ButterKnife.bind(this,root);
    initViews();
    foodDetailViewModel.getMutableLiveDataFood().observe(getViewLifecycleOwner(), foodModel -> {
        displayInfo(foodModel);
    });
    foodDetailViewModel.getMutableLiveDataComment().observe(getViewLifecycleOwner(),commentModel -> {
        submitRatingToFirebase(commentModel);
    });
    return root;
}

private void initViews() {
    waitingDialog = new SpotsDialog.Builder().setCancelable(false).setContext(getContext()).build();

    addonBottomSheetDialog = new BottomSheetDialog(getContext(),R.style.DialogStyle);
    View layout_addon_display = getLayoutInflater().inflate(R.layout.layout_addon_display,null);
    chip_group_addon = (ChipGroup)layout_addon_display.findViewById(R.id.chip_group_addon);
    edt_search = (EditText)layout_addon_display.findViewById(R.id.edt_search);
    addonBottomSheetDialog.setContentView(layout_addon_display);

    addonBottomSheetDialog.setOnDismissListener(dialogInterface -> {
        displayUserSelectedAddon();
        calculateTotalPrice();
    });
}

private void displayUserSelectedAddon() {
    if(Common.selectedFood.getUserSelectedAddon() !=null &&
    Common.selectedFood.getUserSelectedAddon().size() > 0)
    {
        chip_group_user_selected_addon.removeAllViews(); //clear all view
        for(AddonModel addonModel : Common.selectedFood.getUserSelectedAddon()) //Add all available addon to list
        {
            Chip chip = (Chip)getLayoutInflater().inflate(R.layout.layout_chip_with_delete_icon, null);
            chip.setText(new StringBuilder(addonModel.getName()).append("(+$")
            .append(addonModel.getPrice()).append(")"));
            chip.setClickable(false);
            chip.setOnCloseIconClickListener(view -> {
                //Remove when user select delete
                chip_group_user_selected_addon.removeView(view);
                Common.selectedFood.getUserSelectedAddon().remove(addonModel);
                calculateTotalPrice();
            });
            chip_group_user_selected_addon.addView(chip);
        }
    }else if(Common.selectedFood.getUserSelectedAddon().size() == 0)
        chip_group_user_selected_addon.removeAllViews();
}

private void submitRatingToFirebase(CommentModel commentModel) {
    waitingDialog.show();
    //Submit comment to Ref
    FirebaseDatabase.getInstance()
            .getReference(Common.COMMENT_REF)
            .child(Common.selectedFood.getId())
            .push()
            .setValue(commentModel)
            .addOnCompleteListener(task -> {
                if(task.isSuccessful())
                {
                    //After submit to CommentRef, update value in food
                    addRatingToFood(commentModel.getRatingValue());
                }
            });
}

private void addRatingToFood(float ratingValue) {
    FirebaseDatabase.getInstance()
            .getReference(Common.CATEGORY_REF)
            .child(Common.categorySelected.getMenu_id()) //select category
    .child("foods") // select array list 'foods' of this category
    .child(Common.selectedFood.getKey()) //food item is array list
    .addListenerForSingleValueEvent(new ValueEventListener() {
        @Override
        public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
            if(dataSnapshot.exists())
            {
                FoodModel foodModel = dataSnapshot.getValue(FoodModel.class);
                foodModel.setKey(Common.selectedFood.getKey());

                //Apply rating
                if(foodModel.getRatingValue() == null)
                    foodModel.setRatingValue(0d);
                if(foodModel.getRatingCount() == null)
                    foodModel.setRatingCount(0l);
                double sumRating = (foodModel.getRatingValue() * foodModel.getRatingCount())+ratingValue;
                long ratingCount = foodModel.getRatingCount()+1;
                double result = sumRating/ratingCount;

                Map<String,Object> updateData = new HashMap<>();
                updateData.put("ratingValue",result);
                updateData.put("ratingCount",ratingCount);

                //Update data variable
                foodModel.setRatingValue(result);
                foodModel.setRatingCount(ratingCount);

                dataSnapshot.getRef()
                        .updateChildren(updateData)
                        .addOnCompleteListener(task -> {
                            waitingDialog.dismiss();
                            if(task.isSuccessful())
                            {
                                Toast.makeText(getContext(), "Thank you", Toast.LENGTH_SHORT).show();
                                Common.selectedFood = foodModel;
                                foodDetailViewModel.setFoodModel(foodModel); //Call refresh
                            }
                        });

            }
            else
                waitingDialog.dismiss();
        }

        @Override
        public void onCancelled(@NonNull DatabaseError databaseError) {
            waitingDialog.dismiss();
            Toast.makeText(getContext(), ""+databaseError.getMessage(), Toast.LENGTH_SHORT).show();
        }
    });
}

private void displayInfo(FoodModel foodModel) {
    Glide.with(getContext()).load(foodModel.getImage()).into(img_food);
    food_name.setText(new StringBuilder(foodModel.getName()));
    food_description.setText(new StringBuilder(foodModel.getDescription()));
    food_price.setText(new StringBuilder(foodModel.getPrice().toString()));

    if(foodModel.getRatingValue() != null)
        ratingBar.setRating(foodModel.getRatingValue().floatValue());

    ((AppCompatActivity)getActivity())
            .getSupportActionBar()
            .setTitle(Common.selectedFood.getName());

    //Size
    for(SizeModel sizeModel: Common.selectedFood.getSize())
    {
        RadioButton radioButton = new RadioButton(getContext());
        radioButton.setOnCheckedChangeListener((compoundButton, b) -> {
            if(b)
                Common.selectedFood.setUserSelectedSize(sizeModel);
            calculateTotalPrice(); //Update price
        });

        LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(0,
                LinearLayout.LayoutParams.MATCH_PARENT,
                1.0f);
        radioButton.setLayoutParams(params);
        radioButton.setText(sizeModel.getName());
        radioButton.setTag(sizeModel.getPrice());

        rdi_group_size.addView(radioButton);

    }

    if(rdi_group_size.getChildCount() > 0)
    {
        RadioButton radioButton = (RadioButton)rdi_group_size.getChildAt(0);
        radioButton.setChecked(true); //Default first select
    }

    calculateTotalPrice();
}

private void calculateTotalPrice() {
    double totalPrice = Double.parseDouble(Common.selectedFood.getPrice().toString()),displayPrice=0.0;

    //Addon
    if(Common.selectedFood.getUserSelectedAddon() != null && Common.selectedFood.getUserSelectedAddon().size() > 0)
        for(AddonModel addonModel : Common.selectedFood.getUserSelectedAddon())
            totalPrice+=Double.parseDouble(addonModel.getPrice().toString());

    //size
    totalPrice += Double.parseDouble(Common.selectedFood.getUserSelectedSize().getPrice().toString());

    displayPrice = totalPrice * (Integer.parseInt(numberButton.getNumber()));
    displayPrice = Math.round(displayPrice*100.0/100.0);

    food_price.setText(new StringBuilder("").append(Common.formatPrice(displayPrice)).toString());
}

@Override
public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
    //Null
}

@Override
public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
    chip_group_addon.clearCheck();
    chip_group_addon.removeAllViews();

    for(AddonModel addonModel:Common.selectedFood.getAddon())
    {
        if(addonModel.getName().toLowerCase().contains(charSequence.toString().toLowerCase()))
        {
            Chip chip = (Chip)getLayoutInflater().inflate(R.layout.layout_addon_item,null);
            chip.setText(new StringBuilder(addonModel.getName()).append("(+$")
            .append(addonModel.getPrice()).append(")"));
            chip.setOnCheckedChangeListener((compoundButton, b) -> {
                if(b)
                {
                    if (Common.selectedFood.getUserSelectedAddon() == null)
                        Common.selectedFood.setUserSelectedAddon(new ArrayList<>());
                    Common.selectedFood.getUserSelectedAddon().add(addonModel);
                }
            });
            chip_group_addon.addView(chip);
        }
    }
}

@Override
public void afterTextChanged(Editable editable) {

}

尺寸模型.java

public class SizeModel {
private String name;
private Long price;

public SizeModel() {
}

public String getName() {
    return name;
}

public void setName(String name) {
    this.name = name;
}

public Long getPrice() {
    return price;
}

public void setPrice(Long price) {
    this.price = price;
}

标签: android-studio

解决方案


推荐阅读