GridView(日历)性能问题(+70 getView调用,GC_FOR_ALLOC,UI冻结)

时间:2014-01-25 17:29:11

标签: android android-gridview android-adapter

我正在尝试在Android应用中构建月度日历。我的应用使用MainActivityNavigationDrawerFragments。显示日历的片段称为MonthCalendar

GridView用于显示日历。 我的适配器基于droidwalk implementation

我的目标是每天显示一个ImageView和一个TextBox(日期编号)。我从Web服务获取日期数据并将这些数据存储在SQLite数据库中。

MonthFragment.java

public class MonthFragment extends BaseFragment {

    public GridView gridview;
    public GregorianCalendar month, itemmonth;
    public CalendarAdapter adapter;
    public Handler handler;
    private DayRepository dayRepository;
    private List<Day> days;

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

    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_month, null);

        Locale.setDefault(Locale.FRANCE);
        month = (GregorianCalendar) GregorianCalendar.getInstance();

        // Prepare the DB repository
        this.dayRepository = new DayRepository();
        ...
        adapter = new CalendarAdapter(view.getContext(), month);
        adapter.notifyDataSetChanged();
        gridview = (GridView) view.findViewById(R.id.gridView_month);
        gridview.setAdapter(adapter);

        // Handler
        days = new ArrayList<Day>();
        handler = new Handler();
        handler.post(calendarUpdater);

        // Click event next/prev button call refreshCalendar()

        ...
        return view;
    }
    ...
    public void refreshCalendar() {
        TextView title = (TextView) getActivity().findViewById(R.id.title);

        gridview.invalidateViews();
        adapter.refreshDays();
        adapter.notifyDataSetChanged();
        handler.post(calendarUpdater);

        String monthTitle = (String) android.text.format.DateFormat.format("MMMM yyyy", month);
        title.setText(monthTitle.substring(0,1).toUpperCase() + monthTitle.substring(1));
    }

    public Runnable calendarUpdater = new Runnable() {
        @Override
        public void run() {
            days.clear();

            // Fetch data from SQLlite DB
            days = dayRepository.getByMonth(month.get(GregorianCalendar.MONTH)+1, month.get(GregorianCalendar.YEAR));

            adapter.setDays(days);
            adapter.notifyDataSetChanged();
        }
    };

}

CalendarAdapter.java

public class CalendarAdapter extends BaseAdapter {

    private Context mContext;
    private Calendar month;

    public GregorianCalendar pmonth;
    public GregorianCalendar pmonthmaxset;
    private GregorianCalendar selectedDate;

    private int firstDay;
    private int maxWeeknumber;
    private int maxP;
    private int calMaxP;
    private int lastWeekDay;
    private int leftDays;
    private int mnthlength;
    private String itemvalue, curentDateString;
    private DateFormat df;

    public static List<String> dayString;
    private View previousView;

    private List<Day> days;

    public CalendarAdapter(Context c, GregorianCalendar monthCalendar) {
        CalendarAdapter.dayString = new ArrayList<String>();
        month = monthCalendar;
        selectedDate = (GregorianCalendar) monthCalendar.clone();
        mContext = c;
        month.set(GregorianCalendar.DAY_OF_MONTH, 1);
        this.days = new ArrayList<Day>();
        df = new SimpleDateFormat("yyyy-MM-dd", Locale.US);
        curentDateString = df.format(selectedDate.getTime());
        refreshDays();
    }

    public void setDays(List<Day> days) {
        this.days = days;
    }

    public int getCount() {
        return dayString.size();
    }

    public Object getItem(int position) {
        return dayString.get(position);
    }

    public long getItemId(int position) {
        return 0;
    }

    // Create a new view for each item referenced by the Adapter
    public View getView(int position, View convertView, ViewGroup parent) {
        View view = convertView;

        // Keeps reference to avoid future findViewById()
        CalendarViewHolder holder;

        if (view == null) {
            LayoutInflater inflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            view = inflater.inflate(R.layout.calendar_item, null);

            holder = new CalendarViewHolder();
            holder.dayImg = (ImageView) view.findViewById(R.id.date_img);
            holder.dayDescription = (TextView) view.findViewById(R.id.date_desc);
            holder.dayNumber = (TextView) view.findViewById(R.id.date);
            holder.rl_gridDay = (RelativeLayout) view.findViewById(R.id.relativeLayout_gridDay);
            view.setTag(holder);
        } else {
            holder = (CalendarViewHolder) view.getTag();
        }

        String[] separatedTime = dayString.get(position).split("-");
        String gridvalue = separatedTime[2].replaceFirst("^0*", "");

        Log.d("Calendar", "===============> getView() call " + gridvalue);

        // Day is in current month?
        if ((Integer.parseInt(gridvalue) > 1) && (position < firstDay)) {
            // Offdays (before month)
            holder.dayNumber.setClickable(false);
            holder.dayNumber.setFocusable(false);
            holder.rl_gridDay.setVisibility(View.INVISIBLE);
        } else if ((Integer.parseInt(gridvalue) < 7) && (position > 28)) {
            // Offdays (after month)
            holder.dayNumber.setClickable(false);
            holder.dayNumber.setFocusable(false);
            holder.rl_gridDay.setVisibility(View.INVISIBLE);
        } else {
            holder.dayNumber.setTextColor(Color.WHITE);
            holder.rl_gridDay.setVisibility(View.VISIBLE);
        }

        if (dayString.get(position).equals(curentDateString)) {
            setSelected(view);
            previousView = view;
        } else {
            view.setBackgroundResource(R.drawable.list_item_background);
        }

        holder.dayNumber.setText(gridvalue);

        // START

        Day currentDay = null;
        if (date.length() > 0 && days != null) {
            for (Day object : days) {
                if (object.getMday() == Integer.parseInt(gridvalue)) {
                    currentDay = object;
                    break;
                }
            }
        } else {
            holder.dayImg.setVisibility(View.INVISIBLE);
            holder.constellation.setVisibility(View.INVISIBLE);
            holder.dayDescription.setVisibility(View.INVISIBLE);
        }

        if (currentDay != null) {
            DayUtil dayUtil = new DayUtil(currentDay, mContext);

            holder.dayImg.setImageResource(dayUtil.getDrawableId());
            holder.dayDescription.setText(dayUtil.formatDesc());

            holder.dayImg.setVisibility(View.VISIBLE);
            holder.dayDescription.setVisibility(View.VISIBLE);
        }

        // END

        return view;
    }

    public View setSelected(View view) {
        if (previousView != null) {
            previousView.setBackgroundResource(R.drawable.list_item_background);
        }
        previousView = view;
        view.setBackgroundResource(R.drawable.calendar_cell_select);
        return view;
    }

    public void refreshDays() {
        days.clear();
        dayString.clear();

        pmonth = (GregorianCalendar) month.clone();
        // month start day. ie; sun, mon, etc
        firstDay = month.get(GregorianCalendar.DAY_OF_WEEK);
        // finding number of weeks in current month.
        maxWeeknumber = month.getActualMaximum(GregorianCalendar.WEEK_OF_MONTH);
        if(maxWeeknumber >= 6) maxWeeknumber = 5;
        // allocating maximum row number for the gridview.
        mnthlength = maxWeeknumber * 7;
        maxP = getMaxP(); // previous month maximum day 31,30....
        calMaxP = maxP - (firstDay - 1);// calendar offday starting 24,25 ...

        pmonthmaxset = (GregorianCalendar) pmonth.clone();
        pmonthmaxset.set(GregorianCalendar.DAY_OF_MONTH, calMaxP + 1);

        /**
         * filling calendar gridview.
         */
        for (int n = 0; n < mnthlength; n++) {
            itemvalue = df.format(pmonthmaxset.getTime());
            pmonthmaxset.add(GregorianCalendar.DATE, 1);
            dayString.add(itemvalue);
        }

    }

    private int getMaxP() {
        int maxP;
        if (month.get(GregorianCalendar.MONTH) == month.getActualMinimum(GregorianCalendar.MONTH)) {
            pmonth.set((month.get(GregorianCalendar.YEAR) - 1), month.getActualMaximum(GregorianCalendar.MONTH), 1);
        } else {
            pmonth.set(GregorianCalendar.MONTH, month.get(GregorianCalendar.MONTH) - 1);
        }
        maxP = pmonth.getActualMaximum(GregorianCalendar.DAY_OF_MONTH);

        return maxP;
    }

    public static class CalendarViewHolder {
        public ImageView dayImg;
        public TextView dayDescription;
        public RelativeLayout rl_gridDay;
        public TextView dayNumber;
    }

}

DayUtil.java

public class DayUtil {
    private Day day;
    private Context context;
    ...
    /**
     * Return the day image picture ID
     * Dynamic loading of images R.Drawable depending on a day parameter
     */
    public int getDrawable() {
        ...
        return context.getResources().getIdentifier(resName, "drawable", context.getPackageName());
    }
}

第一个问题(性能问题)

GridView类过度调用适配器的getView()方法(或多或少70次)。主UI冻结几秒钟,加载速度非常慢。

我试图将// START// END行之间的操作放在AsyncTask中,但没有任何改进。

  1. 超过70个getView()调用
  2. GC_FOR_ALLOC
  3. logcat的

    01-25 17:07:56.132    3243-3243/com.example.android D/Calendar﹕ ===============> getView() call 29
    01-25 17:07:56.140    3243-3243/com.example.android D/Calendar﹕ ===============> getView() call 29
    01-25 17:07:56.140    3243-3243/com.example.android D/Calendar﹕ ===============> getView() call 30
    01-25 17:07:56.144    3243-3243/com.example.android D/Calendar﹕ ===============> getView() call 31
    01-25 17:07:56.148    3243-3243/com.example.android D/Calendar﹕ ===============> getView() call 1
    01-25 17:07:56.152    3243-3243/com.example.android D/Calendar﹕ ===============> getView() call 2
    01-25 17:07:56.152    3243-3243/com.example.android D/Calendar﹕ ===============> getView() call 3
    01-25 17:07:56.156    3243-3243/com.example.android D/Calendar﹕ ===============> getView() call 4
    01-25 17:07:56.160    3243-3243/com.example.android D/Calendar﹕ ===============> getView() call 5
    01-25 17:07:56.160    3243-3243/com.example.android D/Calendar﹕ ===============> getView() call 6
    01-25 17:07:56.168    3243-3243/com.example.android D/Calendar﹕ ===============> getView() call 7
    01-25 17:07:56.172    3243-3243/com.example.android D/Calendar﹕ ===============> getView() call 8
    01-25 17:07:56.176    3243-3243/com.example.android D/Calendar﹕ ===============> getView() call 9
    01-25 17:07:56.180    3243-3243/com.example.android D/Calendar﹕ ===============> getView() call 10
    01-25 17:07:56.184    3243-3243/com.example.android D/Calendar﹕ ===============> getView() call 11
    01-25 17:07:56.188    3243-3243/com.example.android D/Calendar﹕ ===============> getView() call 12
    01-25 17:07:56.188    3243-3243/com.example.android D/Calendar﹕ ===============> getView() call 13
    01-25 17:07:56.192    3243-3243/com.example.android D/Calendar﹕ ===============> getView() call 14
    01-25 17:07:56.196    3243-3243/com.example.android D/Calendar﹕ ===============> getView() call 15
    01-25 17:07:56.200    3243-3243/com.example.android D/Calendar﹕ ===============> getView() call 16
    01-25 17:07:56.204    3243-3243/com.example.android D/Calendar﹕ ===============> getView() call 17
    01-25 17:07:56.204    3243-3243/com.example.android D/Calendar﹕ ===============> getView() call 18
    01-25 17:07:56.208    3243-3243/com.example.android D/Calendar﹕ ===============> getView() call 19
    01-25 17:07:56.208    3243-3243/com.example.android D/Calendar﹕ ===============> getView() call 20
    01-25 17:07:56.212    3243-3243/com.example.android D/Calendar﹕ ===============> getView() call 21
    01-25 17:07:56.216    3243-3243/com.example.android D/Calendar﹕ ===============> getView() call 22
    01-25 17:07:56.216    3243-3243/com.example.android D/Calendar﹕ ===============> getView() call 23
    01-25 17:07:56.220    3243-3243/com.example.android D/Calendar﹕ ===============> getView() call 24
    01-25 17:07:56.224    3243-3243/com.example.android D/Calendar﹕ ===============> getView() call 25
    01-25 17:07:56.228    3243-3243/com.example.android D/Calendar﹕ ===============> getView() call 26
    01-25 17:07:56.232    3243-3243/com.example.android D/Calendar﹕ ===============> getView() call 27
    01-25 17:07:56.232    3243-3243/com.example.android D/Calendar﹕ ===============> getView() call 28
    01-25 17:07:56.236    3243-3243/com.example.android D/Calendar﹕ ===============> getView() call 29
    01-25 17:07:56.240    3243-3243/com.example.android D/Calendar﹕ ===============> getView() call 30
    01-25 17:07:56.240    3243-3243/com.example.android D/Calendar﹕ ===============> getView() call 31
    01-25 17:07:56.244    3243-3243/com.example.android D/Calendar﹕ ===============> getView() call 1
    01-25 17:07:56.332    3243-3243/com.example.android D/Calendar﹕ ===============> getView() call 29
    01-25 17:07:56.340    3243-3243/com.example.android D/Calendar﹕ ===============> getView() call 29
    01-25 17:07:56.344    3243-3243/com.example.android D/Calendar﹕ ===============> getView() call 30
    01-25 17:07:56.356    3243-3243/com.example.android D/Calendar﹕ ===============> getView() call 31
    01-25 17:07:56.356    3243-3243/com.example.android D/Calendar﹕ ===============> getView() call 1
    01-25 17:07:56.360    3243-3243/com.example.android D/Calendar﹕ ===============> getView() call 2
    01-25 17:07:56.360    3243-3243/com.example.android D/Calendar﹕ ===============> getView() call 3
    01-25 17:07:56.364    3243-3243/com.example.android D/Calendar﹕ ===============> getView() call 4
    01-25 17:07:56.372    3243-3243/com.example.android D/dalvikvm﹕ GC_FOR_ALLOC freed 416K, 4% free 16135K/16752K, paused 8ms, total 9ms
    01-25 17:07:56.416    3243-3243/com.example.android D/Calendar﹕ ===============> getView() call 5
    01-25 17:07:56.452    3243-3243/com.example.android D/dalvikvm﹕ GC_FOR_ALLOC freed 4955K, 31% free 12739K/18312K, paused 7ms, total 7ms
    01-25 17:07:56.464    3243-3243/com.example.android D/Calendar﹕ ===============> getView() call 6
    01-25 17:07:56.492    3243-3243/com.example.android D/Calendar﹕ ===============> getView() call 7
    01-25 17:07:56.520    3243-3243/com.example.android D/Calendar﹕ ===============> getView() call 8
    01-25 17:07:56.528    3243-3243/com.example.android D/dalvikvm﹕ GC_FOR_ALLOC freed 11K, 21% free 14473K/18312K, paused 8ms, total 8ms
    01-25 17:07:56.556    3243-3243/com.example.android D/Calendar﹕ ===============> getView() call 9
    01-25 17:07:56.584    3243-3243/com.example.android D/Calendar﹕ ===============> getView() call 10
    01-25 17:07:56.596    3243-3243/com.example.android D/dalvikvm﹕ GC_FOR_ALLOC freed 7K, 13% free 16029K/18312K, paused 9ms, total 9ms
    01-25 17:07:56.628    3243-3243/com.example.android D/Calendar﹕ ===============> getView() call 11
    01-25 17:07:56.664    3243-3243/com.example.android D/Calendar﹕ ===============> getView() call 12
    01-25 17:07:56.672    3243-3243/com.example.android D/dalvikvm﹕ GC_FOR_ALLOC freed 7K, 4% free 17585K/18312K, paused 7ms, total 7ms
    01-25 17:07:56.704    3243-3243/com.example.android D/Calendar﹕ ===============> getView() call 13
    01-25 17:07:56.712    3243-3243/com.example.android D/dalvikvm﹕ GC_FOR_ALLOC freed 3K, 4% free 18363K/19092K, paused 8ms, total 8ms
    01-25 17:07:56.744    3243-3243/com.example.android D/Calendar﹕ ===============> getView() call 14
    01-25 17:07:56.752    3243-3243/com.example.android D/dalvikvm﹕ GC_FOR_ALLOC freed 3K, 4% free 19141K/19872K, paused 8ms, total 8ms
    01-25 17:07:56.784    3243-3243/com.example.android D/Calendar﹕ ===============> getView() call 15
    01-25 17:07:56.788    3243-3243/com.example.android D/dalvikvm﹕ GC_FOR_ALLOC freed 3K, 4% free 19919K/20652K, paused 6ms, total 6ms
    01-25 17:07:56.820    3243-3243/com.example.android D/Calendar﹕ ===============> getView() call 16
    01-25 17:07:56.820    3243-3243/com.example.android D/Calendar﹕ ===============> getView() call 17
    01-25 17:07:56.832    3243-3243/com.example.android D/dalvikvm﹕ GC_FOR_ALLOC freed 6K, 4% free 20698K/21432K, paused 9ms, total 9ms
    01-25 17:07:56.864    3243-3243/com.example.android D/Calendar﹕ ===============> getView() call 18
    01-25 17:07:56.872    3243-3243/com.example.android D/dalvikvm﹕ GC_FOR_ALLOC freed 3K, 4% free 21476K/22212K, paused 5ms, total 6ms
    01-25 17:07:56.904    3243-3243/com.example.android D/Calendar﹕ ===============> getView() call 19
    01-25 17:07:56.912    3243-3243/com.example.android D/dalvikvm﹕ GC_FOR_ALLOC freed 3K, 4% free 22254K/22992K, paused 7ms, total 7ms
    01-25 17:07:56.940    3243-3243/com.example.android D/Calendar﹕ ===============> getView() call 20
    01-25 17:07:56.948    3243-3243/com.example.android D/dalvikvm﹕ GC_FOR_ALLOC freed 3K, 4% free 23032K/23772K, paused 6ms, total 6ms
    01-25 17:07:56.980    3243-3243/com.example.android D/Calendar﹕ ===============> getView() call 21
    01-25 17:07:57.024    3243-3243/com.example.android D/Calendar﹕ ===============> getView() call 22
    01-25 17:07:57.068    3243-3243/com.example.android D/Calendar﹕ ===============> getView() call 23
    01-25 17:07:57.104    3243-3243/com.example.android D/Calendar﹕ ===============> getView() call 24
    01-25 17:07:57.140    3243-3243/com.example.android D/Calendar﹕ ===============> getView() call 25
    01-25 17:07:57.140    3243-3243/com.example.android D/Calendar﹕ ===============> getView() call 26
    01-25 17:07:57.180    3243-3243/com.example.android D/Calendar﹕ ===============> getView() call 27
    01-25 17:07:57.212    3243-3243/com.example.android D/Calendar﹕ ===============> getView() call 28
    01-25 17:07:57.212    3243-3243/com.example.android D/Calendar﹕ ===============> getView() call 29
    01-25 17:07:57.212    3243-3243/com.example.android D/Calendar﹕ ===============> getView() call 30
    01-25 17:07:57.216    3243-3243/com.example.android D/Calendar﹕ ===============> getView() call 31
    01-25 17:07:57.216    3243-3243/com.example.android D/Calendar﹕ ===============> getView() call 1
    

    有些尝试

    我做错了吗? 你能救我吗?

    谢谢!

0 个答案:

没有答案
相关问题