如何解决空引用错误?我是新来的[重复]

Posted

技术标签:

【中文标题】如何解决空引用错误?我是新来的[重复]【英文标题】:How to solve null references error? Im new at this [duplicate] 【发布时间】:2020-05-20 03:36:15 【问题描述】:

它说我的 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:尝试调用虚拟方法'java.lang.String com.example.CarServiceBooking.Model.Outlet.getOutletId()' 为空 对象引用 在 com.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(未知来源) 在 android.os.Handler.handleCallback(Handler.java:739) 在 android.os.Handler.dispatchMessage(Handler.java:95) 在 android.os.Looper.loop(Looper.java:135) 在 android.app.ActivityThread.main(ActivityThread.java:5254) 在 java.lang.reflect.Method.invoke(本机方法) 在 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();
                        
                    
                );
    

这是我的 Outlet 课程

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

【问题讨论】:

不,它没有。 【参考方案1】:

Common 处出错。您将在此行中遇到错误。

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

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

【讨论】:

我已经在bookingstep1fragment的模型中设置了数据。这是我的代码(QueryDocumentSnapshot documentSnapshot:task.getResult()) Outlet outlet = documentSnapshot.toObject(Outlet.class); outlet.setOutletId(documentSnapshot.getId()); list.add(出口); 我认为你没有为outletId设置数据,或者如果你是从服务器收集数据并设置它的模型,那么你无法从服务器接收到outletId,所以模型中的outletId为空。跨度> 你在 outlet.setOutletId(documentSnapshot.getId()); 下面调试list.add(outlet) 这一行并检查出口数据我认为这里没有为 outletId 设置任何数据。 我已经编辑了问题。我已经为 outletId 设置了数据 你没有定义 Common.currentOutlet = outlet ; addOnCompleteListener 中的任何位置

以上是关于如何解决空引用错误?我是新来的[重复]的主要内容,如果未能解决你的问题,请参考以下文章

用 PHP 发送邮件 [重复]

第六章 函数[DDT书本学习 小甲鱼]

我怎样才能制作这两个盒子。 PS我是新来的颤振[关闭]

我是新来的反应。我想在 React JS 中使用 onClick 事件使用单个状态呈现子组件

任何想法如何解决快速动画背景图片

如何在颤振发布方法中修复“未处理的异常:用于空值的空检查运算符”