0

I am building a calendar app but I am having trouble getting the backend to work. I am able to save/delete and edit my events but I can't get them to display when the user clicks into the calendar. The users are able to view their saved data as they make changes on screen but once they restart the app or click to other views everything is gone. I checked my list content and the details are always displayed as null.

public class CalendarViewWithNotesActivitySDK21_v2 extends Fragment {

private final static int CREATE_EVENT_REQUEST_CODE = 100;

private String[] mShortMonths;
private CalendarView mCalendarView;
private CalendarDialog mCalendarDialog;

private List<CalenderEventModel> mEventList = new ArrayList<>();

private static Context context = null;

public static Intent makeIntent(Context context) {
    return new Intent(context, CalendarViewWithNotesActivitySDK21_v2.class);
}

@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
    context = getActivity();
    setHasOptionsMenu(true);
    View v = inflater.inflate(R.layout.activity_calendar_view_with_notes_sdk_21, container, false);

    //getFirebaseData();

    //mShortMonths = new DateFormatSymbols().getShortMonths();

    initializeUI(v);

    return v;
}

private void getFirebaseData() {
    FirebaseUser user = FirebaseAuth.getInstance().getCurrentUser();
    assert user != null;
    final String uid = user.getUid();
    final FirebaseDatabase db = FirebaseDatabase.getInstance();
    final DatabaseReference ref = db.getReference("Calendar Events").child(uid);

    ref.addValueEventListener(new ValueEventListener() {
        @Override
        public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
            mEventList.clear();
            for(DataSnapshot ds : dataSnapshot.getChildren()) {
                String id = ds.getKey();
                String title = ds.child("title").getValue(String.class);
                Calendar date = ds.child("date").getValue();
                int color = ds.child("color").getValue(Integer.class);
                boolean complete = ds.child("completed").getValue(boolean.class);

                CalenderEventModel model = new CalenderEventModel(id,title,date,color,complete);
                mEventList.add(model);

                //mEventList.add(ds.getValue(CalenderEventModel.class));
            }
        }

        @Override
        public void onCancelled(@NonNull DatabaseError databaseError) {

        }
    });

}

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    getFirebaseData();

    mShortMonths = new DateFormatSymbols().getShortMonths();

    //initializeUI();
}

This is how i save to firebase

 private void save() {

    FirebaseUser user = FirebaseAuth.getInstance().getCurrentUser();
    assert user != null;
    final String uid = user.getUid();
    final FirebaseDatabase database = FirebaseDatabase.getInstance();
    final DatabaseReference ref = database.getReference("Calendar Events").child(uid);
    String key = ref.push().getKey();

    int action = mOriginalEvent != null ? ACTION_EDIT : ACTION_CREATE;
    String id = mOriginalEvent != null ? mOriginalEvent.getID() : key;
    String rawTitle = mTitleView.getText().toString().trim();

    if(mOriginalEvent == null) {
        mOriginalEvent = new CalenderEventModel(
                id,
                rawTitle.isEmpty() ? null : rawTitle,
                mCalendar,
                mColor,
                mIsCompleteCheckBox.isChecked()
        );
        Map<String, Object> childUpdate = new HashMap<>();
        childUpdate.put(key, mOriginalEvent.toFirebaseObject());
        ref.updateChildren(childUpdate, new DatabaseReference.CompletionListener() {
            @Override
            public void onComplete(@Nullable DatabaseError databaseError, @NonNull DatabaseReference databaseReference) {
                if (databaseError == null) {
                    return;
                }
            }
        });
    } else {
        mOriginalEvent.setmTitle(rawTitle.isEmpty() ? null : rawTitle);
        mOriginalEvent.setmDate(mCalendar);
        mOriginalEvent.setmColor(mColor);
        mOriginalEvent.setCompleted(mIsCompleteCheckBox.isChecked());
        ref.child(mOriginalEvent.getID()).setValue(mOriginalEvent);
    }

    setResult(RESULT_OK, new Intent()
            .putExtra(INTENT_EXTRA_ACTION, action)
            .putExtra(INTENT_EXTRA_EVENT, mOriginalEvent));
    finish();

    if (action == ACTION_CREATE)
        overridePendingTransition(R.anim.stay, R.anim.slide_out_down);

}

This is my event modal class

public class CalenderEventModel implements Parcelable {

private String mID;
private String mTitle;
private Calendar mDate;
private int mColor;
private boolean isCompleted;

public CalenderEventModel() {

}

public CalenderEventModel(String id, String title, Calendar date, int color, boolean isCompleted) {
    mID = id;
    mTitle = title;
    mDate = date;
    mColor = color;
    this.isCompleted = isCompleted;
}

public void setmID(String mID) {
    this.mID = mID;
}

public void setmTitle(String mTitle) {
    this.mTitle = mTitle;
}

public void setmDate(Calendar mDate) {
    this.mDate = mDate;
}

public void setmColor(int mColor) {
    this.mColor = mColor;
}

public void setCompleted(boolean completed) {
    isCompleted = completed;
}

public String getID() {
    return mID;
}

public String getTitle() {
    return mTitle;
}

public Calendar getDate() {
    return mDate;
}

public int getColor() {
    return mColor;
}

public boolean isCompleted() {
    return isCompleted;
}

public Map<String, Object> toFirebaseObject() {
    HashMap<String, Object> event = new HashMap<>();
    event.put("mid", mID);
    event.put("title", mTitle);
    event.put("date", mDate);
    event.put("color", mColor);
    event.put("completed", isCompleted);

    return event;
}

protected CalenderEventModel(Parcel in) {
    mID = in.readString();
    mTitle = in.readString();
    mColor = in.readInt();
    mDate = (Calendar) in.readSerializable();
    isCompleted = in.readByte() != 0;
}

@Override
public void writeToParcel(Parcel dest, int flags) {
    dest.writeString(mID);
    dest.writeString(mTitle);
    dest.writeInt(mColor);
    dest.writeSerializable(mDate);
    dest.writeByte((byte) (isCompleted ? 1 : 0));
}

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

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

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

}

In the method to get firebase data, i tried getting the data one by one as seen in the uncommented out statement but i face this error

java.lang.ClassCastException: java.util.HashMap cannot be cast to java.util.Calendar
    at com.example.serenity.CalendarViewWithNotesActivitySDK21_v2$1.onDataChange(CalendarViewWithNotesActivitySDK21_v2.java:91)
    at com.google.firebase.database.core.ValueEventRegistration.fireEvent(com.google.firebase:firebase-database@@19.3.0:75)
    at com.google.firebase.database.core.view.DataEvent.fire(com.google.firebase:firebase-database@@19.3.0:63)
    at com.google.firebase.database.core.view.EventRaiser$1.run(com.google.firebase:firebase-database@@19.3.0:55)
    at android.os.Handler.handleCallback(Handler.java:907)
    at android.os.Handler.dispatchMessage(Handler.java:99)
    at android.os.Looper.loop(Looper.java:223)
    at android.app.ActivityThread.main(ActivityThread.java:7478)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:549)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:941)
Alex Mamo
  • 130,605
  • 17
  • 163
  • 193
Mitsuki
  • 3
  • 2

1 Answers1

0

You are getting the following Exception:

java.lang.ClassCastException: java.util.HashMap cannot be cast to java.util.Calendar

Because you are trying to cast an object of type HashMap to an object of type Calendar. This is actually not possible in Java, because there is no inheritance relationship between them. As I see in the error message, you are trying to do that cast in the onDataChange() method. So the DataSnapshot object actually contains a HashMap and not a Calendar object. Besides that, the Calendar is not a supported data-type in Firebase Realtime Database.

To solve this, try to get the data out of the HashMap object, by iterating through its elements. Also, change to the type of your mDate property to be of type HashMap and not calendar in your CalenderEventModel class.

Alex Mamo
  • 130,605
  • 17
  • 163
  • 193
  • im sorry but im not sure how it works if i change it to Hashmap instead of calendar as i need to use the methods in the calendar class to set the time and date of the event – Mitsuki Jun 17 '20 at 12:04
  • I understand that, but there is no way you can add a Calendar object to the database, thus, you cannot get it back that way. If you need to store dates, you can store as a [ServerValue.TIMESTAMP](https://stackoverflow.com/questions/43584244/how-to-save-the-current-date-time-when-i-add-new-value-to-firebase-realtime-data) or simply as Long values, like in [here](https://stackoverflow.com/questions/11871120/java-time-since-the-epoch). In the end, you can then simply convert to a Calendar object. – Alex Mamo Jun 17 '20 at 12:20
  • hi ive been trying but i cant seem to get it.. is it possible for you to show me by code? – Mitsuki Jun 19 '20 at 06:55
  • Stack Overflow isn't a code writing service. You should make your own attempt given the information in the answer and ask another question if something else comes up. – Alex Mamo Jun 19 '20 at 07:38