首页 > 解决方案 > 如何解决空引用错误?我是新手

问题描述

它说我的 getOutletId() 是空引用,我认为我已经声明了。所以基本上这是一个预订步骤 4。第一步,用户需要从 firestore 中选择出口并选择哪个分支,我已经包含到 setOutlet id。然后第二步将显示工作人员。我从firestore获得的所有信息除了Id,我都是手动完成的。有人可以帮我解决这个问题吗?

这是我在预订步骤 1 片段中设置出口 ID 的地方

private void loadBranchOfCity(String cityName) {
        dialog.show();

        Common.city = cityName;

        branchRef = FirebaseFirestore.getInstance()
                .collection("AllPlace")
                .document(cityName)
                .collection("Branch");

        branchRef.get().addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() {
            @Override
            public void onComplete(@NonNull Task<QuerySnapshot> task) {
                List<Outlet> list = new ArrayList<>();
                if (task.isSuccessful())
                {
                    for(QueryDocumentSnapshot documentSnapshot:task.getResult())
                    {
                        Outlet outlet = documentSnapshot.toObject(Outlet.class);
                        outlet.setOutletId(documentSnapshot.getId());
                        list.add(outlet);
                    }
                    iBranchLoadListener.onBranchLoadSuccess(list);
                }
            }
        }).addOnFailureListener(new OnFailureListener() {
            @Override
            public void onFailure(@NonNull Exception e) {
                iBranchLoadListener.onBranchLoadFailed(e.getMessage());
            }
        });
    }

这是我的预订活动,其中 outletId 开始显示

@OnClick(R.id.btn_next_step)
    void nextClick(){
        if (Common.step < 3 || Common.step == 0)
        {
            Common.step++; //increase
            if (Common.step == 1) //After choose outlet
            {
                if(Common.currentOutlet != null)
                    loadStaffByOutlet(Common.currentOutlet.getOutletId());
            }
            else if(Common.step == 2) //pick time slot
            {
                if(Common.currentStaff != null)
                    loadTimeSlotOfStaff(Common.currentStaff.getStaffId());
            }
            else if(Common.step == 3) //Confirm
            {
                    if(Common.currentTimeSlot != -1)
                    confirmBooking();
            }
            viewPager.setCurrentItem(Common.step);
        }
    }

    private void confirmBooking() {
        //Send broadcast to fragment step four
        Intent intent = new Intent (Common.KEY_CONFIRM_BOOKING);
        localBroadcastManager.sendBroadcast(intent);
    }

    private void loadTimeSlotOfStaff(String staffId) {
        //Send local broadcast to fragment step 3
        Intent intent = new Intent (Common.KEY_DISPLAY_TIME_SLOT);
        localBroadcastManager.sendBroadcast(intent);
    }

    private void loadStaffByOutlet(String outletId) {
        dialog.show();

        //Select all staff of Outlet
        // /AllPlace/Melaka/Branch/RCgub6eOcf2c0s06Soyb/Staff
        if (!TextUtils.isEmpty(Common.city))
        {
            staffRef = FirebaseFirestore.getInstance()
                    .collection("AllPlace")
                    .document(Common.city)
                    .collection("Branch")
                    .document(outletId)
                    .collection("Staff");

            staffRef.get().addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() {
                @Override
                public void onComplete(@NonNull Task<QuerySnapshot> task) {
                    ArrayList<Staff> staffs = new ArrayList<>();
                    for(QueryDocumentSnapshot staffsnapshot:task.getResult())
                    {
                        Staff staff = staffsnapshot.toObject(Staff.class);
                        staff.setPassword(""); //Remove password because this is client app
                        staff.setStaffId(staffsnapshot.getId());//get id of staff

                        staffs.add(staff);
                    }
                    //Send Broadcast to BookingStep2Fragment to load Recycler
                    Intent intent = new Intent(Common.KEY_STAFF_LOAD_DONE);
                    intent.putParcelableArrayListExtra(Common.KEY_STAFF_LOAD_DONE,staffs);
                    localBroadcastManager.sendBroadcast(intent);

                    dialog.dismiss();
                }
            }).addOnFailureListener(new OnFailureListener() {
                @Override
                public void onFailure(@NonNull Exception e) {
                    dialog.dismiss();
                }
            });

        }
    }

这是我的日志猫

进程:com.example.CarServiceBooking,PID:12259 java.lang.NullPointerException:尝试在 com 的空对象引用上调用虚拟方法“java.lang.String com.example.CarServiceBooking.Model.Outlet.getOutletId()”。 example.CarServiceBooking.Fragment.BookingStep4Fragment$3$2.onSuccess(BookingStep4Fragment.java:216) 在 com.example.CarServiceBooking.Fragment.BookingStep4Fragment$3$2.onSuccess(BookingStep4Fragment.java:199) 在 com.google.android.gms.tasks。 zzn.run(Unknown Source) at android.os.Handler.handleCallback(Handler.java:739) at android.os.Handler.dispatchMessage(Handler.java:95) at android.os.Looper.loop(Looper.java: 135) 在 android.app.ActivityThread.main(ActivityThread.java:5254) 在 java.lang.reflect.Method.invoke(Native Method) 在 java.lang.reflect.Method.invoke(Method.java:372) 在 com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit. java:903) 在 com.android.internal.os.ZygoteInit.main(ZygoteInit.java:698)

这是我的普通课

    public class Common {
        public static final String KEY_ENABLE_BUTTON_NEXT = "ENABLE_BUTTON_NEXT";
        public static final String KEY_OUTLET_STORE = "OUTLET_SAVE";
        public static final String KEY_STAFF_LOAD_DONE = "STAFF_LOAD_DONE";
        public static final String KEY_DISPLAY_TIME_SLOT = "DISPLAY_TIME_SLOT";
        public static final String KEY_STEP = "STEP" ;
        public static final String KEY_STAFF_SELECTED = "STAFF_SELECTED";
        public static final Object DISABLE_TAG = "DISABLE";
        public static final String KEY_TIME_SLOT = "TIME_SLOT";
        public static final String KEY_CONFIRM_BOOKING = "CONFIRM_BOOKING";
        public static final String IS_LOGIN = "IsLogin";
        public static final String EVENT_URI_CACHE = "URI_EVENT_SAVE";
        public static final String TITLE_KEY = "title";
        public static final String CONTENT_KEY = "content";
        private static final String LOGGED_KEY = "LOGGED";
        public static User currentUser;
        public static Outlet currentOutlet;
        public static Staff currentStaff;
        public static int step = 0; //init first step is 0
        public static String city = "";
        public static int currentTimeSlot = -1;
        public static final int TIME_SLOT_TOTAL = 9;
        public static Calendar bookingDate = Calendar.getInstance();
        public static SimpleDateFormat simpleDateFormat = new SimpleDateFormat("dd_MM_yyyy"); //only use when need format key
        public static BookingInformation currentBooking;
        public static String currentBookingId = "";

这是我的 BookingStep4Fragment,logcat 说它是空引用

private void addToUserBooking(final BookingInformation bookingInformation) {
        resetStaticData();
        getActivity().finish(); //close activity
        Toast.makeText(getContext(), "Success!", Toast.LENGTH_SHORT).show();

        //First, create new collection
        CollectionReference userBooking = FirebaseFirestore.getInstance()
                .collection("Users")
                .document(Common.currentUser.getPhone())
                .collection("Booking");

        //Check if exist document in this collection
        //Get Current Date
        Calendar calendar = Calendar.getInstance();
        calendar.add(Calendar.DATE,0);
        calendar.set(Calendar.HOUR_OF_DAY,0);
        calendar.set(Calendar.MINUTE,0);

        Timestamp toDayTimeStamp = new Timestamp(calendar.getTime());

        userBooking
                .whereGreaterThanOrEqualTo("timestamp",toDayTimeStamp)
                .whereEqualTo("done",false)
                .limit(1) //only take 1
                .get()
                .addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() {
                    @Override
                    public void onComplete(@NonNull Task<QuerySnapshot> task) {
                        if(task.isSuccessful())
                        {
                            //set data
                            userBooking.document()
                                    .set(bookingInformation)
                                    .addOnSuccessListener(new OnSuccessListener<Void>() {
                                        @Override
                                        public void onSuccess(Void aVoid)
                                        {
                                            //Create Notification
                                            MyNotification myNotification = new MyNotification();
                                            myNotification.setUid(UUID.randomUUID().toString());
                                            myNotification.setTitle("New Booking ");
                                            myNotification.setContent("You have a new appointment for customer vehicle with "+Common.currentUser.getName());
                                            myNotification.setRead(false); // we will only filter notification with 'read' is false on staff app
                                            myNotification.setServerTimestamp(FieldValue.serverTimestamp());

                                            //Submit notification to 'Notifications' collection of Staff
                                            FirebaseFirestore.getInstance()
                                                    .collection("AllPlace")
                                                    .document(Common.city)
                                                    .collection("Branch")
                                                    .document(Common.currentOutlet.getOutletId())
                                                    .collection("Staff")
                                                    .document(Common.currentStaff.getStaffId())
                                                    .collection("Notifications") //if it not available, it will be create automatically
                                                    .document(myNotification.getUid()) //create unique key
                                                    .set(myNotification)
                                                    .addOnSuccessListener(new OnSuccessListener<Void>() {
                                                        @Override
                                                        public void onSuccess(Void aVoid) {
                                                            //First get Token base on staff id
                                                            FirebaseFirestore.getInstance()
                                                                    .collection("Tokens")
                                                                    .whereEqualTo("userPhone",Common.currentStaff.getUsername())
                                                                    .limit(1)
                                                                    .get()
                                                                    .addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() {
                                                                        @Override
                                                                        public void onComplete(@NonNull Task<QuerySnapshot> task) {
                                                                            if (task.isSuccessful() && task.getResult().size() > 0)
                                                                            {
                                                                                MyToken myToken = new MyToken();
                                                                                for (DocumentSnapshot tokenSnapShot : task.getResult())
                                                                                    myToken = tokenSnapShot.toObject(MyToken.class);

                                                                                //Create data to send
                                                                                FCMSendData sendRequest = new FCMSendData();
                                                                                Map<String,String> dataSend = new HashMap<>();
                                                                                dataSend.put(Common.TITLE_KEY, "New Booking");
                                                                                dataSend.put(Common.CONTENT_KEY,"You have new booking from user "+Common.currentUser.getName());

                                                                                sendRequest.setTo(myToken.getToken());
                                                                                sendRequest.setData(dataSend);

                                                                                compositeDisposable.add(ifcmApi.sendNotification(sendRequest)
                                                                                        .subscribeOn(Schedulers.io())
                                                                                        .observeOn(AndroidSchedulers.mainThread())
                                                                                        .subscribe(new Consumer<FCMResponse>() {
                                                                                            @Override
                                                                                            public void accept(FCMResponse fcmResponse) throws Exception {
                                                                                                dialog.dismiss();;

                                                                                                addToCalendar(Common.bookingDate,
                                                                                                        Common.convertTimeSlotToString(Common.currentTimeSlot));
                                                                                                resetStaticData();
                                                                                                getActivity().finish(); //Close activity
                                                                                                Toast.makeText(getContext(), "Success!", Toast.LENGTH_SHORT).show();
                                                                                            }
                                                                                        }, new Consumer<Throwable>() {
                                                                                            @Override
                                                                                            public void accept(Throwable throwable) throws Exception {
                                                                                                Log.d("NOTIFICATION_ERROR",throwable.getMessage());
                                                                                                addToCalendar(Common.bookingDate,
                                                                                                        Common.convertTimeSlotToString(Common.currentTimeSlot));
                                                                                                resetStaticData();
                                                                                                getActivity().finish(); //Close activity
                                                                                                Toast.makeText(getContext(), "Success!", Toast.LENGTH_SHORT).show();


                                                                                            }
                                                                                        }));

                                                                            }
                                                                        }
                                                                    });
                                                        }
                                                    });
                                        }
                                    })
                                    .addOnFailureListener(new OnFailureListener() {
                                        @Override
                                        public void onFailure(@NonNull Exception e) {
                                            Toast.makeText(getContext(), e.getMessage(), Toast.LENGTH_SHORT).show();
                                        }
                                    });
                        }
                        else
                        {
                            if(dialog.isShowing())
                                dialog.dismiss();

                            resetStaticData();
                            getActivity().finish(); //close activity
                            Toast.makeText(getContext(), "Success!", Toast.LENGTH_SHORT).show();
                        }
                    }
                });
    }

这是我的奥特莱斯课

public class Outlet implements Parcelable {
    private String name,address,website, phone,openHours,outletId;

    public Outlet() {
    }

    public String getName() {
        return name;
    }

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

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    public String getWebsite() {
        return website;
    }

    public void setWebsite(String website) {
        this.website = website;
    }

    public String getPhone() {
        return phone;
    }

    public void setPhone(String phone) {
        this.phone = phone;
    }

    public String getOpenHours() {
        return openHours;
    }

    public void setOpenHours(String openHours) {
        this.openHours = openHours;
    }

    public String getOutletId() {
        return outletId;
    }

    public void setOutletId(String outletId) {
        this.outletId = outletId;
    }

    protected Outlet(Parcel in) {
        name = in.readString();
        address = in.readString();
        website = in.readString();
        phone = in.readString();
        openHours = in.readString();
        outletId = in.readString();
    }

    public static final Creator<Outlet> CREATOR = new Creator<Outlet>() {
        @Override
        public Outlet createFromParcel(Parcel in) {
            return new Outlet(in);
        }

        @Override
        public Outlet[] newArray(int size) {
            return new Outlet[size];
        }
    };

    @Override
    public int describeContents() {
        return 0;
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeString(name);
        dest.writeString(address);
        dest.writeString(website);
        dest.writeString(phone);
        dest.writeString(openHours);
        dest.writeString(outletId);
    }
}

标签: androidandroid-fragmentsnullpointerexceptionnull-object-pattern

解决方案


常见错误。您将在此行中收到错误。

    public static User currentUser;
    public static Outlet currentOutlet;
    public static Staff currentStaff;
    public static BookingInformation currentBooking;

因为,你没有初始化。你应该这样做;

  public static User currentUser = new User ();
    public static Outlet currentOutlet = new Outlet ();
    public static Staff currentStaff =  new Staff ();
    public static BookingInformation currentBooking = new BookingInformation();

可能是你会得到另一个错误。我显示上面的代码,你没有为模型设置任何值。只有你从模型中获取值。你应该在从模型中获取数据之前在模型中设置数据。


推荐阅读