我有自定义日历。对于月份视图,我使用网格视图。 在日历的每一天,显示每月的日期数和每天的事件数。 为了达到这个目标,我在getView中询问每一天的事件。 为了提高性能,我在get视图中使用了一个holder。 但不幸的是我的应用程序经常崩溃,如果我从一个月切换到下一个月它很慢。如果用户点击下个月的按钮,则会调用setGridCellAdapterToDate。
public void setGridCellAdapterToDate(int month, int year)
{
adapter = new GridCellAdapter(getActivity().getApplicationContext(), calendarView,R.id.calendar_day_gridcell, month, year);
_calendar.set(year, month - 1, _calendar.get(Calendar.DAY_OF_MONTH));
currentMonth.setText(dateFormatter.format(dateTemplate, _calendar.getTime()));
adapter.notifyDataSetChanged();
calendarView.setAdapter(adapter);
calendarView.setSelected(true);
}
有没有办法提高日历的效果?
public class GridCellAdapter extends BaseAdapter implements OnClickListener, OnLongClickListener
{
private static final String tag = "GridCellAdapter";
private final Context _context;
private final List<String> list;
private static final int DAY_OFFSET = 1;
private final String[] weekdays = new String[]{"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};
private final String[] months = {"January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"};
private final int[] daysOfMonth = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
private final int month, year;
private int daysInMonth, prevMonthDays;
private int currentDayOfMonth;
private int currentWeekDay;
private Button gridcell;
private TextView num_events_per_day;
private final HashMap eventsPerMonthMap;
SimpleDateFormat("dd-MMM-yyyy");
public GridCellAdapter(Context context, GridView gv, int textViewResourceId, int month, int year)
{
super();
this._context = context;
this.list = new ArrayList<String>();
this.month = month;
this.year = year;
this.mGv = gv;
Log.d(tag, "==> Passed in Date FOR Month: " + month + " " + "Year: " + year);
Calendar calendar = Calendar.getInstance();
setCurrentDayOfMonth(calendar.get(Calendar.DAY_OF_MONTH));
setCurrentWeekDay(calendar.get(Calendar.DAY_OF_WEEK));
Log.d(tag, "New Calendar:= " + calendar.getTime().toString());
Log.d(tag, "CurrentDayOfWeek :" + getCurrentWeekDay());
Log.d(tag, "CurrentDayOfMonth :" + getCurrentDayOfMonth());
// Print Month
printMonth(month, year);
// Find Number of Events
eventsPerMonthMap = findNumberOfEventsPerMonth(year, month);
}
private String getMonthAsString(int i)
{
return months[i];
}
private String getWeekDayAsString(int i)
{
return weekdays[i];
}
private int getNumberOfDaysOfMonth(int i)
{
return daysOfMonth[i];
}
public String getItem(int position)
{
return list.get(position);
}
public int getCount()
{
return list.size();
}
/**
* Prints Month
*
* @param mm
* @param yy
*/
private void printMonth(int mm, int yy)
{
Log.d(tag, "==> printMonth: mm: " + mm + " " + "yy: " + yy);
// The number of days to leave blank at
// the start of this month.
int trailingSpaces = 0;
int leadSpaces = 0;
int daysInPrevMonth = 0;
int prevMonth = 0;
int prevYear = 0;
int nextMonth = 0;
int nextYear = 0;
int currentMonth = mm - 1;
String currentMonthName = getMonthAsString(currentMonth);
daysInMonth = getNumberOfDaysOfMonth(currentMonth);
Log.d(tag, "Current Month: " + " " + currentMonthName + " having " + daysInMonth + " days.");
// Gregorian Calendar : MINUS 1, set to FIRST OF MONTH
GregorianCalendar cal = new GregorianCalendar(yy, currentMonth, 1);
Log.d(tag, "Gregorian Calendar:= " + cal.getTime().toString());
Calendar caltemp = Calendar.getInstance();
Integer intMonat = caltemp.get(Calendar.MONTH);
if (currentMonth == 11)
{
prevMonth = currentMonth - 1;
daysInPrevMonth = getNumberOfDaysOfMonth(prevMonth);
nextMonth = 0;
prevYear = yy;
nextYear = yy + 1;
Log.d(tag, "*->PrevYear: " + prevYear + " PrevMonth:" + prevMonth + " NextMonth: " + nextMonth + " NextYear: " + nextYear);
}
else if (currentMonth == 0)
{
prevMonth = 11;
prevYear = yy - 1;
nextYear = yy;
daysInPrevMonth = getNumberOfDaysOfMonth(prevMonth);
nextMonth = 1;
Log.d(tag, "**--> PrevYear: " + prevYear + " PrevMonth:" + prevMonth + " NextMonth: " + nextMonth + " NextYear: " + nextYear);
}
else
{
prevMonth = currentMonth - 1;
nextMonth = currentMonth + 1;
nextYear = yy;
prevYear = yy;
daysInPrevMonth = getNumberOfDaysOfMonth(prevMonth);
Log.d(tag, "***---> PrevYear: " + prevYear + " PrevMonth:" + prevMonth + " NextMonth: " + nextMonth + " NextYear: " + nextYear);
}
// Compute how much to leave before before the first day of the
// month.
// getDay() returns 0 for Sunday.
int currentWeekDay = cal.get(Calendar.DAY_OF_WEEK) - 1;
trailingSpaces = currentWeekDay;
Log.d(tag, "Week Day:" + currentWeekDay + " is " + getWeekDayAsString(currentWeekDay));
Log.d(tag, "No. Trailing space to Add: " + trailingSpaces);
Log.d(tag, "No. of Days in Previous Month: " + daysInPrevMonth);
if (cal.isLeapYear(cal.get(Calendar.YEAR)) && mm == 1)
{
++daysInMonth;
}
// Trailing Month days
for (int i = 0; i < trailingSpaces; i++)
{
Log.d(tag, "PREV MONTH:= " + prevMonth + " => " + getMonthAsString(prevMonth) + " " + String.valueOf((daysInPrevMonth - trailingSpaces + DAY_OFFSET) + i));
list.add(String.valueOf((daysInPrevMonth - trailingSpaces + DAY_OFFSET) + i) + "-GREY" + "-" + getMonthAsString(prevMonth) + "-" + prevYear);
}
// Current Month Days
for (int i = 1; i <= daysInMonth; i++)
{
Log.d(currentMonthName, String.valueOf(i) + " " + getMonthAsString(currentMonth) + " " + yy);
if (i == getCurrentDayOfMonth() && mm == intMonat+1)
{
list.add(String.valueOf(i) + "-BLUE" + "-" + getMonthAsString(currentMonth) + "-" + yy);
}
else
{
list.add(String.valueOf(i) + "-WHITE" + "-" + getMonthAsString(currentMonth) + "-" + yy);
}
}
// Leading Month days
for (int i = 0; i < list.size() % 7; i++)
{
Log.d(tag, "NEXT MONTH:= " + getMonthAsString(nextMonth));
list.add(String.valueOf(i + 1) + "-GREY" + "-" + getMonthAsString(nextMonth) + "-" + nextYear);
}
}
/**
* NOTE: YOU NEED TO IMPLEMENT THIS PART Given the YEAR, MONTH, retrieve
* ALL entries from a SQLite database for that month. Iterate over the
* List of All entries, and get the dateCreated, which is converted into
* day.
*
* @param year
* @param month
* @return
*/
private HashMap findNumberOfEventsPerMonth(int year, int month)
{
HashMap map = new HashMap<String, Integer>();
// DateFormat dateFormatter2 = new DateFormat();
//
// String day = dateFormatter2.format("dd", dateCreated).toString();
//
// if (map.containsKey(day))
// {
// Integer val = (Integer) map.get(day) + 1;
// map.put(day, val);
// }
// else
// {
// map.put(day, 1);
// }
return map;
}
public long getItemId(int position)
{
return position;
}
public View getView(int position, View convertView, ViewGroup parent)
{
ViewHolder holder;
Integer intRowNumber = 5;
View row = convertView;
if (row == null)
{
LayoutInflater inflater = (LayoutInflater) _context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
row = inflater.inflate(R.layout.calendar_day_gridcell, parent, false);
//convertView = inflater.inflate(R.layout.calendar_day_gridcell,parent,false);
holder = new ViewHolder();
holder.text = (TextView)row.findViewById(R.id.num_events_per_day);
holder.gridcell= (Button)row.findViewById(R.id.calendar_day_gridcell);
//holder.EventsofMonth = openCalendar.getEventsOfMonth(getActivity(), caltemp.getTimeInMillis(),strCalendarId);
row.setTag(holder);
} else {
holder = (ViewHolder)row.getTag();
}
int intHeight = mGv.getHeight();
intHeight = intHeight/intRowNumber;
AbsListView.LayoutParams param = new AbsListView.LayoutParams(
android.view.ViewGroup.LayoutParams.FILL_PARENT,
mGv.getHeight()/intRowNumber);
//row.setLayoutParams(param);
row.setLayoutParams(param);
// Get a reference to the Day gridcell
//gridcell = (Button) row.findViewById(R.id.calendar_day_gridcell);
//gridcell.setOnClickListener(new MyOnClickListener(position));
holder.gridcell.setOnClickListener(this);
holder.gridcell.setOnLongClickListener(this);
// ACCOUNT FOR SPACING
Log.d(tag, "Current Day: " + getCurrentDayOfMonth());
String[] day_color = list.get(position).split("-");
String theday = day_color[0];
String themonth = day_color[2];
String theyear = day_color[3];
String selection = "((" + CalendarContract.Events.DTSTART
+ " >= ?) AND (" + CalendarContract.Events.DTEND + " <= ?) AND (" + CalendarContract.Events.DELETED + " = ?) AND (" + CalendarContract.Events.CALENDAR_ID + " = ?))";
if ((!eventsPerMonthMap.isEmpty()) && (eventsPerMonthMap != null))
{
if (eventsPerMonthMap.containsKey(theday))
{
//num_events_per_day = (TextView) row.findViewById(R.id.num_events_per_day);
Integer numEvents = (Integer) eventsPerMonthMap.get(theday);
//num_events_per_day.setText(numEvents.toString());
}
}
// Set the Day GridCell
holder.gridcell.setText(theday);
holder.gridcell.setTag(theday + "-" + themonth + "-" + theyear);
Log.d(tag, "Setting GridCell " + theday + "-" + themonth + "-" + theyear);
if (day_color[1].equals("GREY"))
{
holder.gridcell.setTextColor(Color.LTGRAY);
}
if (day_color[1].equals("WHITE"))
{
holder.gridcell.setTextColor(Color.WHITE);
}
if (day_color[1].equals("BLUE"))
{
//gridcell.setTextColor(getResources().getColor(R.color.static_text_color));
holder.gridcell.setTextColor(Color.BLUE);
DisplayMetrics metrics;
metrics = getActivity().getApplicationContext().getResources().getDisplayMetrics();
float Textsize = 0;
Textsize = holder.gridcell.getTextSize()/metrics.density;
holder.gridcell.setTextSize(Textsize+4);
}
//ermittle die Anzahl der Events an diesem Tag und schreibe sie in num_events_per_day
Integer intAnzEventsonSelectedDay = 0;
//num_events_per_day = (TextView) row.findViewById(R.id.num_events_per_day);
String strCurrentDatum = theday + "-" + month + "-" + year;
SimpleDateFormat sdf = new SimpleDateFormat("dd-MM-yyyy");
Date dateObj = null;
try {
dateObj = sdf.parse(strCurrentDatum);
} catch (ParseException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
String temp = dateObj.toString();
caltemp.setTime(dateObj);
Cursor curCalendar = openCalendar.getEventsOfDay(getActivity(), caltemp.getTimeInMillis(),strCalendarId);
curCalendar.moveToFirst();
intAnzEventsonSelectedDay = curCalendar.getCount();
if (intAnzEventsonSelectedDay > 4){
holder.text.setTextColor(Color.RED);
} else{
//
}
holder.text.setText(intAnzEventsonSelectedDay.toString());
return row;
}
答案 0 :(得分:0)
我认为性能问题的一部分实际上是你做了多少工作才能达到一个月。我能告诉你的最好的事情是首先从使用Calendar
切换到使用MonthDisplayHelper
。它是一个内置的Android类,基本上可以帮助您布局一个月。它的格式也很好,每周都会分成一个int数组。虽然仍然有Calendar
,但它是保持当前信息的好方法。更重要的是,不是从一天加载每个事件,而是首先加载月份,然后使用AsyncTask
在关闭UI线程后加载单个事件。想象一下,每个月都有几个事件,那就是在你向用户展示一个月的视图之前需要进行大量的计算。一个很好的例子就是googles默认日历。如果您有足够的事件,您会注意到它们在月视图出现后开始加载。从可用性角度来看,它具有强大的功能。