I have a method that inserts into the Android Calendar an event. You can see a simplified snippet in two steps: 1)declare the variables 2) I put them into a kind of array that in the end will insert it into the calendar, and it works flawlessy:

    private void InsertCalendarEvent() {

     //1)here I declare the variables startMills and endMills
    Calendar beginTime = Calendar.getInstance();
    beginTime.set(2018, 9, 11, 8, 30);
    startMillis = beginTime.getTimeInMillis();
    Calendar endTime = Calendar.getInstance();
    endTime.set(2018, 9, 11, 10, 30);
    endMillis = endTime.getTimeInMillis();

    //2)here insert the values in the db with put(to buid the array)
    // and then finalizing with insert
    cr = this.getContentResolver();
    ContentValues values = new ContentValues();
    values.put(CalendarContract.Events.DTSTART, startMillis);
    values.put(CalendarContract.Events.DTEND, endMillis);
    values.put(CalendarContract.Events.TITLE, editTextValue);
    values.put(CalendarContract.Events.DESCRIPTION, "Time to Run!");
    Uri uri = cr.insert(CalendarContract.Events.CONTENT_URI, values);
    }//end of the method

Now my use case is that I need to insert the same event at different times. So I am wondering which design pattern I should use to do that to avoid duplications. Basically I need to change the point "1)" the 2 variables of the time startMillis and endMillis, and maintain iterating i guess the point "2)" so that the two different time variables go into the point "2" and different events get inserted

I thought different approaches 1)REALLY BAD. Repeat all the code every time writing consecutive methods as

//TODO and so on

2)Split the insertCalendarEvent in two methods, somehow refactoring the code in another class, maybe using a POJO, ArrayList with Map<>, but I am not sure how to implement

3) Create more classes to maintain the Single Responsibility but I do not know how to do it

What is the way a good architect would proceed with this use case?


Would be the second solution the way to go, avoiding any ArrayList and POJO?

1)Easiest but bad The easiest solution duplicate a lot of code:

 //just pass equal methods with different settings

2)Better in the same class without using POJO:

//with an addEvent(Long startTime,Long endTime)

The easiest way: let the calendar do recurrence for you

Elaborating on Bart's answer, according to the API documentation you may insert a recurring event by providing a recurrence rule (RRULE). This rule is expressed as a String which syntax and semantic is described in RFC 2445 section 4.3.10. You can find an interesting example here.

Iterating for creating non-recurring events

But may be your use case requires the creation of independent events. Or maybe you consider to later move to the creation intent that doesn't allow recurring events. Or the recurrence rule is too complex to fit in the RFC 2445 constraints.

In this case, your option 2 would be the way to go. For example:

  1. Create a MyEvent class for representing the subset of events you want to create (e.g. year, month, day, starthr, startmin, endhr, endmin, title, etc.).
  2. Change your InsertCalendarEvent() to take a MyEvent as argument: so this function becomes general purpose.
  3. Create an InsertCalendarEvents() method with a Collection of MyEvents as argument. This method would just iterate through the collection (using an iterator) and call InsertCalendarEvent().
  4. When you need to insert the events, you would just have to generate a collection of MyEvents (for example an ArrayList) and invoke InsertCalendarEvents().

Now, not knowing more about your application, it's difficult to say if it's the best approach. Here, MyEvent plays a passive DTO role. But you could also opt for an active record approach and let MyEvent save itself to the calendar (in this case you should sore the ID returned in the URI in case the event should be modified later on).

Your edit about avoiding POJOs

Using a MyEvent class has the advantage of being reusable and avoiding having methods with too many arguments.

However, if you think it's an overkill and really have only the time that varies between the successive repeating events, you may of course opt for a simpler approach and invoke a method with just the date and time as parameters, exactly as you envisage it.

Between the two alternatives, I'd rather recommend to go for your second one, so to avoid repeating very similar code in very similar methods. But doing so requires some hourly calculations, to prepare the parameters for the call (e.g 30 hours later could be another month of another year). I'd therefore suggest considering the following method:

    addEventWithOffset(startTime,EndTime, 1) ;
    addEventWithOffset(startTime,EndTime, 6) ;
    addEventWithOffset(startTime,EndTime, 8) ;
    addEventWithOffset(startTime,EndTime, 30) ;
  //with an addEventWithOffset(Long startTime,Long endTime, int offsetInHours)
  • I miss something. InsertCalendarEvents(myEventPojo) how should be implemented, in a new class, but principally where/when should I do myEventPojo.setTimeBegin? When/where exactly I should use .add to the Collection( I guess you mean for Collection an ArrayList). I know it depends but at least a vanilla/simple case which one would be? Sorry for the questions, but that is why I delayed my answer. My difficulty is that I do not need just one InsertCalendarEvent but several InsertCalendarEventAfterNHOurs. Aug 17 '18 at 7:17
  • @trocchietto whether you keep the method where it is, or move it to the new class, setBeginTime has to remain in the method and take its parameters from the MyEvent attributes. But as you get it via the static getInstance of the calendar, it shouldn't matter in which class it is invoked. Generating the MyEvent instances and adding them to the ArrayList would be done in another method of your application, independently of the calendar. Typically, if you'd insert an event every N hours, you'd certainly do this in a loop.
    – Christophe
    Aug 17 '18 at 8:41
  • I get it @Christophe, I think I came up with an easier solution without using any Pojo and collection/Map. Please see EDIT point 2.Thank you I am learning a lot Aug 17 '18 at 8:59
  • @trocchietto ok, I see. I've added a section in my answer for some final remarks about your alternative approach
    – Christophe
    Aug 17 '18 at 9:27
  • Thanks accepted Reply, I am impressed by the level of your answers and CV Aug 17 '18 at 10:07

Before proceeding with this use case, I would first check some conditions.

  1. Do we really need multiple copies of the same calendar entry with different dates/times, or do we actually want a repeating entry?
  2. Does our target calendar support the notion of repeating calendar entries?

If the answer is yes to both, then I would update the InsertCalendarEvent function such that it can also insert repeating calendar entries.

If the answer to either question is no, then I would change the InsertCalendarEvent function to take at least the start time as a parameter. The end time could be calculated from the duration of the event. Optionally, you can also pass the other information that the function needs (end-time/duration, title, description) as parameters.
Then you can call the InsertCalendarEvent function for all the relevant start times.

When passing the start time to the function, do that as a Calendar object (or another object that represents a point in time and is convenient for the caller). The conversion to milliseconds is an internal detail of InsertCalendarEvent that its callers shouldn't be bothered with.

  • Thanks Bart, please what do you mean for" then I would update the InsertCalendarEvent function such that it can also insert repeating calendar entries." I do not get how can I update the function, should I maybe use an Array? Aug 15 '18 at 13:14
  • Bart thank you for your kind reply, I am going to accept the second question because is more related to my use case Aug 15 '18 at 15:49

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.