gridview性能问题

时间:2013-10-27 18:36:37

标签: android performance android-gridview android-calendar

我有自定义日历。对于月份视图,我使用网格视图。 在日历的每一天,显示每月的日期数和每天的事件数。 为了达到这个目标,我在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;
        }

1 个答案:

答案 0 :(得分:0)

我认为性能问题的一部分实际上是你做了多少工作才能达到一个月。我能告诉你的最好的事情是首先从使用Calendar切换到使用MonthDisplayHelper。它是一个内置的Android类,基本上可以帮助您布局一个月。它的格式也很好,每周都会分成一个int数组。虽然仍然有Calendar,但它是保持当前信息的好方法。更重要的是,不是从一天加载每个事件,而是首先加载月份,然后使用AsyncTask在关闭UI线程后加载单个事件。想象一下,每个月都有几个事件,那就是在你向用户展示一个月的视图之前需要进行大量的计算。一个很好的例子就是googles默认日历。如果您有足够的事件,您会注意到它们在月视图出现后开始加载。从可用性角度来看,它具有强大的功能。