Skip to content

Commit e56c1f4

Browse files
author
Jens Claes
committed
Dynamic prefetch range.
1 parent 9f9b25b commit e56c1f4

File tree

3 files changed

+123
-78
lines changed

3 files changed

+123
-78
lines changed
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
package com.alamkanak.weekview;
2+
3+
import java.util.Calendar;
4+
import java.util.List;
5+
6+
public class MonthLoader implements WeekViewLoader {
7+
8+
private WeekView.MonthChangeListener mOnMonthChangeListener;
9+
public MonthLoader(WeekView.MonthChangeListener listener){
10+
this.mOnMonthChangeListener = listener;
11+
}
12+
13+
@Override
14+
public double toWeekViewPeriodIndex(Calendar instance){
15+
return instance.get(Calendar.YEAR)*12 + instance.get(Calendar.MONTH) + (instance.get(Calendar.DAY_OF_MONTH)-1)/30.0;
16+
}
17+
18+
@Override
19+
public List<WeekViewEvent> onLoad(int periodIndex){
20+
return mOnMonthChangeListener.onMonthChange(periodIndex/12,periodIndex%12+1);
21+
}
22+
23+
24+
public WeekView.MonthChangeListener getOnMonthChangeListener() {
25+
return mOnMonthChangeListener;
26+
}
27+
28+
public void setOnMonthChangeListener(WeekView.MonthChangeListener onMonthChangeListener) {
29+
this.mOnMonthChangeListener = onMonthChangeListener;
30+
}
31+
}

library/src/main/java/com/alamkanak/weekview/WeekView.java

Lines changed: 69 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -64,10 +64,13 @@ public class WeekView extends View {
6464
private Paint mEventBackgroundPaint;
6565
private float mHeaderColumnWidth;
6666
private List<EventRect> mEventRects;
67+
private List<WeekViewEvent> mPreviousPeriodEvents;
68+
private List<WeekViewEvent> mCurrentPeriodEvents;
69+
private List<WeekViewEvent> mNextPeriodEvents;
6770
private TextPaint mEventTextPaint;
6871
private Paint mHeaderColumnBackgroundPaint;
6972
private Scroller mStickyScroller;
70-
private int mFetchedMonths[] = new int[3];
73+
private int mFetchedPeriod = -1; // the middle period the calendar has fetched.
7174
private boolean mRefreshEvents = false;
7275
private float mDistanceY = 0;
7376
private float mDistanceX = 0;
@@ -104,7 +107,7 @@ public class WeekView extends View {
104107
// Listeners.
105108
private EventClickListener mEventClickListener;
106109
private EventLongPressListener mEventLongPressListener;
107-
private MonthChangeListener mMonthChangeListener;
110+
private WeekViewLoader mWeekViewLoader;
108111
private EmptyViewClickListener mEmptyViewClickListener;
109112
private EmptyViewLongPressListener mEmptyViewLongPressListener;
110113
private DateTimeInterpreter mDateTimeInterpreter;
@@ -427,7 +430,9 @@ private void drawHeaderRowAndEvents(Canvas canvas) {
427430

428431
// Get more events if necessary. We want to store the events 3 months beforehand. Get
429432
// events only when it is the first iteration of the loop.
430-
if (mEventRects == null || mRefreshEvents || (dayNumber == leftDaysWithGaps + 1 && mFetchedMonths[1] != day.get(Calendar.MONTH)+1 && day.get(Calendar.DAY_OF_MONTH) == 15)) {
433+
if (mEventRects == null || mRefreshEvents ||
434+
(dayNumber == leftDaysWithGaps + 1 && mFetchedPeriod != (int) mWeekViewLoader.toWeekViewPeriodIndex(day) &&
435+
Math.abs(mFetchedPeriod - mWeekViewLoader.toWeekViewPeriodIndex(day)) > 0.5)) {
431436
getMoreEvents(day);
432437
mRefreshEvents = false;
433438
}
@@ -644,59 +649,60 @@ public EventRect(WeekViewEvent event, WeekViewEvent originalEvent, RectF rectF)
644649
* @param day The day where the user is currently is.
645650
*/
646651
private void getMoreEvents(Calendar day) {
647-
648-
// Delete all events if its not current month +- 1.
649-
deleteFarMonths(day);
650-
651652
// Get more events if the month is changed.
652653
if (mEventRects == null)
653654
mEventRects = new ArrayList<EventRect>();
654-
if (mMonthChangeListener == null && !isInEditMode())
655+
if (mWeekViewLoader == null && !isInEditMode())
655656
throw new IllegalStateException("You must provide a MonthChangeListener");
656657

657658
// If a refresh was requested then reset some variables.
658659
if (mRefreshEvents) {
659660
mEventRects.clear();
660-
mFetchedMonths = new int[3];
661+
mPreviousPeriodEvents = null;
662+
mCurrentPeriodEvents = null;
663+
mNextPeriodEvents = null;
664+
mFetchedPeriod = -1;
661665
}
662666

663-
// Get events of previous month.
664-
int previousMonth = (day.get(Calendar.MONTH) == 0?12:day.get(Calendar.MONTH));
665-
int nextMonth = (day.get(Calendar.MONTH)+2 == 13 ?1:day.get(Calendar.MONTH)+2);
666-
int[] lastFetchedMonth = mFetchedMonths.clone();
667-
if (mFetchedMonths[0] < 1 || mFetchedMonths[0] != previousMonth || mRefreshEvents) {
668-
if (!containsValue(lastFetchedMonth, previousMonth) && !isInEditMode()){
669-
List<WeekViewEvent> events = mMonthChangeListener.onMonthChange((previousMonth==12)?day.get(Calendar.YEAR)-1:day.get(Calendar.YEAR), previousMonth);
670-
sortEvents(events);
671-
for (WeekViewEvent event: events) {
672-
cacheEvent(event);
673-
}
674-
}
675-
mFetchedMonths[0] = previousMonth;
676-
}
677-
678-
// Get events of this month.
679-
if (mFetchedMonths[1] < 1 || mFetchedMonths[1] != day.get(Calendar.MONTH)+1 || mRefreshEvents) {
680-
if (!containsValue(lastFetchedMonth, day.get(Calendar.MONTH)+1) && !isInEditMode()) {
681-
List<WeekViewEvent> events = mMonthChangeListener.onMonthChange(day.get(Calendar.YEAR), day.get(Calendar.MONTH) + 1);
682-
sortEvents(events);
683-
for (WeekViewEvent event : events) {
684-
cacheEvent(event);
685-
}
686-
}
687-
mFetchedMonths[1] = day.get(Calendar.MONTH)+1;
688-
}
689-
690-
// Get events of next month.
691-
if (mFetchedMonths[2] < 1 || mFetchedMonths[2] != nextMonth || mRefreshEvents) {
692-
if (!containsValue(lastFetchedMonth, nextMonth) && !isInEditMode()) {
693-
List<WeekViewEvent> events = mMonthChangeListener.onMonthChange(nextMonth == 1 ? day.get(Calendar.YEAR) + 1 : day.get(Calendar.YEAR), nextMonth);
694-
sortEvents(events);
695-
for (WeekViewEvent event : events) {
696-
cacheEvent(event);
667+
if(mWeekViewLoader != null){
668+
int periodToFetch = (int) mWeekViewLoader.toWeekViewPeriodIndex(day);
669+
if (!isInEditMode() && (mFetchedPeriod < 0 || mFetchedPeriod != periodToFetch || mRefreshEvents)) {
670+
List<WeekViewEvent> previousPeriodEvents = null;
671+
List<WeekViewEvent> currentPeriodEvents = null;
672+
List<WeekViewEvent> nextPeriodEvents = null;
673+
674+
if(mPreviousPeriodEvents != null && mCurrentPeriodEvents != null && mNextPeriodEvents != null){
675+
if(periodToFetch == mFetchedPeriod-1){
676+
currentPeriodEvents = mPreviousPeriodEvents;
677+
nextPeriodEvents = mCurrentPeriodEvents;
678+
}else if(periodToFetch == mFetchedPeriod){
679+
previousPeriodEvents = mPreviousPeriodEvents;
680+
currentPeriodEvents = mCurrentPeriodEvents;
681+
nextPeriodEvents = mNextPeriodEvents;
682+
}else if(periodToFetch == mFetchedPeriod+1){
683+
previousPeriodEvents = mCurrentPeriodEvents;
684+
currentPeriodEvents = mNextPeriodEvents;
685+
}
697686
}
687+
if(currentPeriodEvents == null)
688+
currentPeriodEvents = mWeekViewLoader.onLoad(periodToFetch);
689+
if(previousPeriodEvents == null)
690+
previousPeriodEvents = mWeekViewLoader.onLoad(periodToFetch-1);
691+
if(nextPeriodEvents == null)
692+
nextPeriodEvents = mWeekViewLoader.onLoad(periodToFetch+1);
693+
694+
695+
//clear events
696+
mEventRects.clear();
697+
sortAndCacheEvents(previousPeriodEvents);
698+
sortAndCacheEvents(currentPeriodEvents);
699+
sortAndCacheEvents(nextPeriodEvents);
700+
701+
mPreviousPeriodEvents = previousPeriodEvents;
702+
mCurrentPeriodEvents = currentPeriodEvents;
703+
mNextPeriodEvents = nextPeriodEvents;
704+
mFetchedPeriod = periodToFetch;
698705
}
699-
mFetchedMonths[2] = nextMonth;
700706
}
701707

702708
// Prepare to calculate positions of each events.
@@ -745,6 +751,13 @@ private void cacheEvent(WeekViewEvent event) {
745751
mEventRects.add(new EventRect(event, event, null));
746752
}
747753

754+
private void sortAndCacheEvents(List<WeekViewEvent> events){
755+
sortEvents(events);
756+
for(WeekViewEvent event : events){
757+
cacheEvent(event);
758+
}
759+
}
760+
748761
/**
749762
* Sorts the events in ascending order.
750763
* @param events The events to be sorted.
@@ -873,38 +886,6 @@ private boolean isTimeAfterOrEquals(Calendar time1, Calendar time2) {
873886
return !(time1 == null || time2 == null) && time1.getTimeInMillis() >= time2.getTimeInMillis();
874887
}
875888

876-
/**
877-
* Deletes the events of the months that are too far away from the current month.
878-
* @param currentDay The current day.
879-
*/
880-
private void deleteFarMonths(Calendar currentDay) {
881-
882-
if (mEventRects == null) return;
883-
884-
Calendar nextMonth = (Calendar) currentDay.clone();
885-
nextMonth.add(Calendar.MONTH, 1);
886-
nextMonth.set(Calendar.DAY_OF_MONTH, nextMonth.getActualMaximum(Calendar.DAY_OF_MONTH));
887-
nextMonth.set(Calendar.HOUR_OF_DAY, 12);
888-
nextMonth.set(Calendar.MINUTE, 59);
889-
nextMonth.set(Calendar.SECOND, 59);
890-
891-
Calendar prevMonth = (Calendar) currentDay.clone();
892-
prevMonth.add(Calendar.MONTH, -1);
893-
prevMonth.set(Calendar.DAY_OF_MONTH, 1);
894-
prevMonth.set(Calendar.HOUR_OF_DAY, 0);
895-
prevMonth.set(Calendar.MINUTE, 0);
896-
prevMonth.set(Calendar.SECOND, 0);
897-
898-
List<EventRect> newEvents = new ArrayList<EventRect>();
899-
for (EventRect eventRect : mEventRects) {
900-
boolean isFarMonth = eventRect.event.getStartTime().getTimeInMillis() > nextMonth.getTimeInMillis() || eventRect.event.getEndTime().getTimeInMillis() < prevMonth.getTimeInMillis();
901-
if (!isFarMonth) newEvents.add(eventRect);
902-
}
903-
mEventRects.clear();
904-
mEventRects.addAll(newEvents);
905-
}
906-
907-
908889
/////////////////////////////////////////////////////////////////
909890
//
910891
// Functions related to setting and getting the properties.
@@ -920,11 +901,21 @@ public EventClickListener getEventClickListener() {
920901
}
921902

922903
public MonthChangeListener getMonthChangeListener() {
923-
return mMonthChangeListener;
904+
if(mWeekViewLoader instanceof MonthLoader)
905+
return ((MonthLoader) mWeekViewLoader).getOnMonthChangeListener();
906+
return null;
924907
}
925908

926909
public void setMonthChangeListener(MonthChangeListener monthChangeListener) {
927-
this.mMonthChangeListener = monthChangeListener;
910+
this.mWeekViewLoader = new MonthLoader(monthChangeListener);
911+
}
912+
913+
public WeekViewLoader getWeekViewLoader(){
914+
return mWeekViewLoader;
915+
}
916+
917+
public void setWeekViewLoader(WeekViewLoader loader){
918+
this.mWeekViewLoader = loader;
928919
}
929920

930921
public EventLongPressListener getEventLongPressListener() {
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
package com.alamkanak.weekview;
2+
3+
import java.util.Calendar;
4+
import java.util.List;
5+
6+
public interface WeekViewLoader {
7+
/**
8+
* Convert a date into a double that will be used to reference when you're loading data.
9+
*
10+
* All periods that have the same integer part, define one period. Dates that are later in time should have a greater return value.
11+
*
12+
* @param instance the date
13+
* @return The period index in which the date falls (floating point number).
14+
*/
15+
public double toWeekViewPeriodIndex(Calendar instance);
16+
17+
/**
18+
* Load the events within the period
19+
* @param periodIndex the period to load
20+
* @return A list with the events of this period
21+
*/
22+
public List<WeekViewEvent> onLoad(int periodIndex);
23+
}

0 commit comments

Comments
 (0)